Skip to content

Commit

Permalink
Merge pull request #37 from Projeto-Pindorama/timeout-impl
Browse files Browse the repository at this point in the history
timeout implementation
  • Loading branch information
takusuman authored Feb 21, 2024
2 parents 4fcfd6a + 0a0a9bc commit 81c81ce
Show file tree
Hide file tree
Showing 9 changed files with 924 additions and 3 deletions.
6 changes: 6 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Release 240220
* [NEW] seq: Stone-simple implementation; needs some improvement yet.
* [NEW] watch: Complete, simple and stable implementation.
* [NEW] timeout: Complete implementation with extended payloads.
* readlink: Different help messages for both UCB and default variants.

Release 230503
* chroot: "docs: Update date at chroot.8 manual page."
* chroot: "chore: Remove comment, will move to GitHub"
Expand Down
5 changes: 3 additions & 2 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ SUBDIRS = build libwchar libcommon libuxre _install \
paste pathchk pg pgrep pr printenv printf priocntl ps psrinfo pwd \
random readlink renice rm rmdir \
sdiff sed seq setpgrp shl sleep sort spell split stty su sum sync \
tabs tail tapecntl tar tcopy tee test time touch tr true tsort tty \
ul uname uniq units users watch wc what who whoami whodo xargs yes
tabs tail tapecntl tar tcopy tee test time timeout touch tr true \
tsort tty ul uname uniq units users watch wc what who whoami whodo \
xargs yes

dummy: makefiles all

Expand Down
18 changes: 18 additions & 0 deletions timeout/Makefile.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
all: timeout

timeout: timeout.o sigtable.o
$(LD) $(LDFLAGS) timeout.o sigtable.o $(LCOMMON) $(LWCHAR) $(LIBS) -o timeout

timeout.o: timeout.c
$(CC) -std=c99 -Wall $(CFLAGS) $(CPPFLAGS) $(XO5FL) $(IWCHAR) $(ICOMMON) -I. -g -c timeout.c

sigtable.o: sigtable.c
$(CC) $(CPPFLAGS) -c sigtable.c

install: all
$(UCBINST) -c timeout $(ROOT)$(DEFBIN)/timeout
$(STRIP) $(ROOT)$(DEFBIN)/timeout
$(MANINST) -c -m 644 timeout.1 $(ROOT)$(MANDIR)/man1/timeout.1

clean:
rm -f timeout timeout.o sigtable.o core log *~
Empty file added timeout/debug.txt
Empty file.
149 changes: 149 additions & 0 deletions timeout/sigtable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* sigtable.h - signal map-like struct.
*/
/*
* Derived from kill/strsig.c
*
* Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
* Copyright (C) 2023, 2024: Luiz Antônio (takusuman)
*
* SPDX-Licence-Identifier: CDDL-1.0
*/

#include <signal.h>

struct sig_strlist {
int signum;
char *signame;
};

static const struct sig_strlist sig_strs[] = {
{ 0, "EXIT" }, /* UNKNOWN SIGNAL */
{ SIGHUP, "HUP" }, /* Hangup */
{ SIGINT, "INT" }, /* Interrupt */
{ SIGQUIT, "QUIT" }, /* Quit */
{ SIGILL, "ILL" }, /* Illegal Instruction */
{ SIGTRAP, "TRAP" }, /* Trace/Breakpoint Trap */
{ SIGABRT, "ABRT" }, /* Abort */
#ifdef SIGIOT
{ SIGIOT, "IOT" }, /* Input/Output Trap */
#endif
#ifdef SIGEMT
{ SIGEMT, "EMT" }, /* Emulation Trap */
#endif
#ifdef SIGFPE
{ SIGFPE, "FPE" }, /* Arithmetic Exception */
#endif
#ifdef SIGKILL
{ SIGKILL, "KILL" }, /* Killed */
#endif
#ifdef SIGBUS
{ SIGBUS, "BUS" }, /* Bus Error */
#endif
#ifdef SIGSEGV
{ SIGSEGV, "SEGV" }, /* Segmentation Fault */
#endif
#ifdef SIGSYS
{ SIGSYS, "SYS" }, /* Bad System Call */
#endif
#ifdef SIGPIPE
{ SIGPIPE, "PIPE" }, /* Broken Pipe */
#endif
#ifdef SIGALRM
{ SIGALRM, "ALRM" }, /* Alarm Clock */
#endif
#ifdef SIGTERM
{ SIGTERM, "TERM" }, /* Terminated */
#endif
#ifdef SIGUSR1
{ SIGUSR1, "USR1" }, /* User Signal 1 */
#endif
#ifdef SIGUSR2
{ SIGUSR2, "USR2" }, /* User Signal 2 */
#endif
#ifdef SIGCLD
{ SIGCLD, "CLD" }, /* Child Status Changed */
#endif
#ifdef SIGCHLD
{ SIGCHLD, "CHLD" }, /* Child Status Changed */
#endif
#ifdef SIGPWR
{ SIGPWR, "PWR" }, /* Power-Fail/Restart */
#endif
#ifdef SIGWINCH
{ SIGWINCH, "WINCH" }, /* Window Size Change */
#endif
#ifdef SIGURG
{ SIGURG, "URG" }, /* Urgent Socket Condition */
#endif
#ifdef SIGPOLL
{ SIGPOLL, "POLL" }, /* Pollable Event */
#endif
#ifdef SIGIO
{ SIGIO, "IO" }, /* Input/Output Now Possible */
#endif
#ifdef SIGSTOP
{ SIGSTOP, "STOP" }, /* Stopped (signal) */
#endif
#ifdef SIGTSTP
{ SIGTSTP, "TSTP" }, /* Stopped (user) */
#endif
#ifdef SIGCONT
{ SIGCONT, "CONT" }, /* Continued */
#endif
#ifdef SIGTTIN
{ SIGTTIN, "TTIN" }, /* Stopped (tty input) */
#endif
#ifdef SIGTTOU
{ SIGTTOU, "TTOU" }, /* Stopped (tty output) */
#endif
#ifdef SIGVTALRM
{ SIGVTALRM, "VTALRM" }, /* Virtual Timer Expired */
#endif
#ifdef SIGPROF
{ SIGPROF, "PROF" }, /* Profiling Timer Expired */
#endif
#ifdef SIGXCPU
{ SIGXCPU, "XCPU" }, /* Cpu Limit Exceeded */
#endif
#ifdef SIGXFSZ
{ SIGXFSZ, "XFSZ" }, /* File Size Limit Exceeded */
#endif
#ifdef SIGWAITING
{ SIGWAITING, "WAITING" }, /* No runnable lwp */
#endif
#ifdef SIGLWP
{ SIGLWP, "LWP" }, /* Inter-lwp signal */
#endif
#ifdef SIGFREEZE
{ SIGFREEZE, "FREEZE" }, /* Checkpoint Freeze */
#endif
#ifdef SIGTHAW
{ SIGTHAW, "THAW" }, /* Checkpoint Thaw */
#endif
#ifdef SIGCANCEL
{ SIGCANCEL, "CANCEL" }, /* Thread Cancellation */
#endif
#ifdef SIGLOST
{ SIGLOST, "LOST" }, /* Resource Lost */
#endif
#ifdef SIGSTKFLT
{ SIGSTKFLT, "STKFLT" }, /* Stack Fault On Coprocessor */
#endif
#ifdef SIGINFO
{ SIGINFO, "INFO" }, /* Status Request From Keyboard */
#endif
#ifdef SIG_2_STR_WITH_RT_SIGNALS
{ SIGRTMIN, "RTMIN" }, /* First Realtime Signal */
{ SIGRTMIN+1, "RTMIN+1" }, /* Second Realtime Signal */
{ SIGRTMIN+2, "RTMIN+2" }, /* Third Realtime Signal */
{ SIGRTMIN+3, "RTMIN+3" }, /* Fourth Realtime Signal */
{ SIGRTMAX-3, "RTMAX-3" }, /* Fourth Last Realtime Signal */
{ SIGRTMAX-2, "RTMAX-2" }, /* Third Last Realtime Signal */
{ SIGRTMAX-1, "RTMAX-1" }, /* Second Last Realtime Signal */
{ SIGRTMAX, "RTMAX" }, /* Last Realtime Signal */
#endif /* SIG_2_STR_WITH_RT_SIGNALS */

/* If this is removed bad things happen dont remove this */
{ -1, NULL }
};
28 changes: 28 additions & 0 deletions timeout/takefive.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/sh
# takefive.sh: test script for timeout(1), takes
# seconds as argument.
# Copyright (c) 2023, 2024 Luiz Antônio Rangel.
#
# This script is public domain, no more, no less.

main() {
for SIG in ABRT ALRM HUP INT TERM; do
eval "trap 'handle_signal $SIG' $SIG"
done
take=${1:-5}
printf 1>&2 'Sleeping %d seconds...\n' $take
while [ $take -gt 0 ]; do
take=$(($take - 1))
printf '%d... ' $take
sleep 1
done
sleep $take
return 3
}

handle_signal() { # function input: string signal
s=$1
printf 'Caught %s\n' "$1"
}

main $1
158 changes: 158 additions & 0 deletions timeout/timeout.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
.\"
.\" Copyright(C) 2024 Luiz Antônio Rangel. All rights reserved.
.\"
.\" SPDX-Licence-Identifier: Zlib
.\"
.TH TIMEOUT 1 "2/20/24" "Heirloom Toolchest" "User Commands"
.SH NAME
timeout \- execute a command with a time limit
.SH SYNOPSIS
\fBtimeout\fR [\fB\-k\fR \fItime\fR]
[\fB\-s\fR \fIsignal\fR] [\-fp]
\fItime\fR \fIcommand\fR [\fIargument\fR ...]
.SH DESCRIPTION
.I Timeout
executes a specified \fIcommand\fR and
attempts to terminate it after an
also specified \fItime\fR.
Per default, it sends signal 15
(terminate, alias SIGTERM), but the
signal can be redefined (see option
'\fI\-s\fR').
If the duration is a zero value, the
timer is disabled (see timer_settime(2)),
ergo there will not be any signal sent
to the specified \fIcommand\fR's process.
.PP
It accepts the following options:
.TP
.B \-k \fItime\fR
Sets a complementary time for tolerance
before sending a final signal 9 (SIGKILL)
to \fIcommand\fR if it's still executing.
.TP
.B \-s \fIsignal\fR
Sets a signal to be sent instead of
signal 15 (terminate). It's defined
per a decimal number or its symbolic
name (see kill(1) '\-l' option).
.br
If it's defined as 9 (SIGKILL), it
has an immediate effect and annuls
the '\-k' option.
.TP
.B \-f
Permits that \fIcommand\fR runs as
foreground and recieves signals
from the terminal; per using this
option, the children processes that
\fIcommand\fR may create will not be
terminated with it even in case of
the timer timing out.
.TP
.B \-p
Keep \fIcommand\fR's exit status
instead of using this program's
default.
.SH "DURATION FORMATTING"
\fItime\fR can be specified as a
fractional number by using a full
stop or a comma as the decimal
separator.
The default value are seconds
unless a time unit is specified per
its single-letter identifier; in
ascend order, the supported units
are:
.TP
.I s
seconds
.TP
.I m
minutes
.TP
.I h
hours
.TP
.I d
days
.SH DIAGNOSTICS
Exit status is 124 if the timer expired
and the \-p option was not set, 126 if
the command could be found, but could not
be executed and 127 if the command could
not be found.
.SH EXAMPLES
This program has different possible
applications in one's routine, here are some:
.br
Lets suppose you need to check if your system
is connected to the Internet and that it can
successfully connect to a server in less than
5 seconds, you can use timeout along with nc(1):
.LP
.RS
.sp
.nf
% timeout -p 5 nc -vz pindorama.dob.jp 80
% echo $?
0
.fi
.sp
.RE
In another example, you have a project and
start experiencing hangings at some part after
a contributor sent a patch, but you do not know
the part nor the file that was broken; since
you know that it should not take more than
half a minute to pass that part, you can use
timeout and visualize precisely where it hangs
per enabling debug at the shell interpreter:
.IP \& 2
.BI "% timeout 0,5m /bin/ksh -x ./build.ksh"
.LP
.SH NOTES
Although this implementation being \fIsœur\fR
with BSDs' implementations since it shares some
parts of code with it, it does not support long
options as GNU (and BSDs') does, so some shell
scripts may not work unchanged with this
implementation.
.br
An abideable approach for solving this problem
could be an small check/wrapper for the
timeout command in case of utilizing the \-f or
the \-p options in its long format.
.RS
.sp
.nf
if test \`getconf HEIRLOOM_TOOLCHEST_VERSION\` \-ge 20240220
then
timeout \-p \-k\fItime\fR \fItime\fR \fIcommand\fR
else
timeout \-\-preserve\-duration \-\-kill\-after \fItime\fR \fItime\fR \fIcommand\fR
fi
.fi
.sp
.RE
.PP
This implementation supports intervals using
both European or Anglo decimal separators,
GNU doesn't.
.PP
In contrast to OpenBSD's \(em and any other
implementation thoroughly based and/or ported
from FreeBSD 10.3R \(em, this implementation
supports nanoseconds as the interval instead
of microseconds. This can change in the future
depending on your platform, though.
.SH "SEE ALSO"
exec(3), fork(2), kill(1), signal(2),
timer_settime(2), itimerspec(3type),
wait(2)
.SH HISTORY
The timeout utility first appeared as a proposal
in BusyBox mailing lists in February 3, 2006,
but this version have payloads closer to the
timeout found at GNU Coreutils 7.0,
released in 05 October, 2008.
Loading

0 comments on commit 81c81ce

Please sign in to comment.