OpenCoverage

timeout.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/src/timeout.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* timeout -- run a command with bounded time-
2 Copyright (C) 2008-2018 Free Software Foundation, Inc.-
3-
4 This program is free software: you can redistribute it and/or modify-
5 it under the terms of the GNU General Public License as published by-
6 the Free Software Foundation, either version 3 of the License, or-
7 (at your option) any later version.-
8-
9 This program is distributed in the hope that it will be useful,-
10 but WITHOUT ANY WARRANTY; without even the implied warranty of-
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-
12 GNU General Public License for more details.-
13-
14 You should have received a copy of the GNU General Public License-
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */-
16-
17-
18/* timeout - Start a command, and kill it if the specified timeout expires-
19-
20 We try to behave like a shell starting a single (foreground) job,-
21 and will kill the job if we receive the alarm signal we setup.-
22 The exit status of the job is returned, or one of these errors:-
23 EXIT_TIMEDOUT 124 job timed out-
24 EXIT_CANCELED 125 internal error-
25 EXIT_CANNOT_INVOKE 126 error executing job-
26 EXIT_ENOENT 127 couldn't find job to exec-
27-
28 Caveats:-
29 If user specifies the KILL (9) signal is to be sent on timeout,-
30 the monitor is killed and so exits with 128+9 rather than 124.-
31-
32 If you start a command in the background, which reads from the tty-
33 and so is immediately sent SIGTTIN to stop, then the timeout-
34 process will ignore this so it can timeout the command as expected.-
35 This can be seen with 'timeout 10 dd&' for example.-
36 However if one brings this group to the foreground with the 'fg'-
37 command before the timer expires, the command will remain-
38 in the stop state as the shell doesn't send a SIGCONT-
39 because the timeout process (group leader) is already running.-
40 To get the command running again one can Ctrl-Z, and do fg again.-
41 Note one can Ctrl-C the whole job when in this state.-
42 I think this could be fixed but I'm not sure the extra-
43 complication is justified for this scenario.-
44-
45 Written by Pádraig Brady. */-
46-
47#include <config.h>-
48#include <getopt.h>-
49#include <stdio.h>-
50#include <sys/types.h>-
51#include <signal.h>-
52#if HAVE_PRCTL-
53# include <sys/prctl.h>-
54#endif-
55#include <sys/wait.h>-
56-
57#include "system.h"-
58#include "c-strtod.h"-
59#include "xstrtod.h"-
60#include "sig2str.h"-
61#include "operand2sig.h"-
62#include "error.h"-
63#include "quote.h"-
64-
65#if HAVE_SETRLIMIT-
66/* FreeBSD 5.0 at least needs <sys/types.h> and <sys/time.h> included-
67 before <sys/resource.h>. Currently "system.h" includes <sys/time.h>. */-
68# include <sys/resource.h>-
69#endif-
70-
71/* NonStop circa 2011 lacks both SA_RESTART and siginterrupt. */-
72#ifndef SA_RESTART-
73# define SA_RESTART 0-
74#endif-
75-
76#define PROGRAM_NAME "timeout"-
77-
78#define AUTHORS proper_name ("Padraig Brady")-
79-
80static int timed_out;-
81static int term_signal = SIGTERM; /* same default as kill command. */-
82static pid_t monitored_pid;-
83static double kill_after;-
84static bool foreground; /* whether to use another program group. */-
85static bool preserve_status; /* whether to use a timeout status or not. */-
86static bool verbose; /* whether to diagnose timeouts or not. */-
87static char const* command;-
88-
89/* for long options with no corresponding short option, use enum */-
90enum-
91{-
92 FOREGROUND_OPTION = CHAR_MAX + 1,-
93 PRESERVE_STATUS_OPTION-
94};-
95-
96static struct option const long_options[] =-
97{-
98 {"kill-after", required_argument, NULL, 'k'},-
99 {"signal", required_argument, NULL, 's'},-
100 {"verbose", no_argument, NULL, 'v'},-
101 {"foreground", no_argument, NULL, FOREGROUND_OPTION},-
102 {"preserve-status", no_argument, NULL, PRESERVE_STATUS_OPTION},-
103 {GETOPT_HELP_OPTION_DECL},-
104 {GETOPT_VERSION_OPTION_DECL},-
105 {NULL, 0, NULL, 0}-
106};-
107-
108/* Start the timeout after which we'll receive a SIGALRM.-
109 Round DURATION up to the next representable value.-
110 Treat out-of-range values as if they were maximal,-
111 as that's more useful in practice than reporting an error.-
112 '0' means don't timeout. */-
113static void-
114settimeout (double duration, bool warn)-
115{-
116-
117/* timer_settime() provides potentially nanosecond resolution.-
118 setitimer() is more portable (to Darwin for example),-
119 but only provides microsecond resolution and thus is-
120 a little more awkward to use with timespecs, as well as being-
121 deprecated by POSIX. Instead we fallback to single second-
122 resolution provided by alarm(). */-
123-
124#if HAVE_TIMER_SETTIME-
125 struct timespec ts = dtotimespec (duration);-
126 struct itimerspec its = { {0, 0}, ts };-
127 timer_t timerid;-
128 if (timer_create (CLOCK_REALTIME, NULL, &timerid) == 0)
timer_create (...&timerid) == 0Description
TRUEevaluated 143 times by 1 test
Evaluated by:
  • timeout
FALSEnever evaluated
0-143
129 {-
130 if (timer_settime (timerid, 0, &its, NULL) == 0)
timer_settime ...id *)0) ) == 0Description
TRUEevaluated 143 times by 1 test
Evaluated by:
  • timeout
FALSEnever evaluated
0-143
131 return;
executed 143 times by 1 test: return;
Executed by:
  • timeout
143
132 else-
133 {-
134 if (warn)
warnDescription
TRUEnever evaluated
FALSEnever evaluated
0
135 error (0, errno, _("warning: timer_settime"));
never executed: error (0, (*__errno_location ()) , dcgettext (((void *)0), "warning: timer_settime" , 5) );
0
136 timer_delete (timerid);-
137 }
never executed: end of block
0
138 }-
139 else if (warn && errno != ENOSYS)
warnDescription
TRUEnever evaluated
FALSEnever evaluated
(*__errno_location ()) != 38Description
TRUEnever evaluated
FALSEnever evaluated
0
140 error (0, errno, _("warning: timer_create"));
never executed: error (0, (*__errno_location ()) , dcgettext (((void *)0), "warning: timer_create" , 5) );
0
141#endif-
142-
143 unsigned int timeint;-
144 if (UINT_MAX <= duration)
(0x7fffffff * ...U) <= durationDescription
TRUEnever evaluated
FALSEnever evaluated
0
145 timeint = UINT_MAX;
never executed: timeint = (0x7fffffff * 2U + 1U) ;
0
146 else-
147 {-
148 unsigned int duration_floor = duration;-
149 timeint = duration_floor + (duration_floor < duration);-
150 }
never executed: end of block
0
151 alarm (timeint);-
152}
never executed: end of block
0
153-
154/* send SIG avoiding the current process. */-
155-
156static int-
157send_sig (pid_t where, int sig)-
158{-
159 /* If sending to the group, then ignore the signal,-
160 so we don't go into a signal loop. Note that this will ignore any of the-
161 signals registered in install_cleanup(), that are sent after we-
162 propagate the first one, which hopefully won't be an issue. Note this-
163 process can be implicitly multithreaded due to some timer_settime()-
164 implementations, therefore a signal sent to the group, can be sent-
165 multiple times to this process. */-
166 if (where == 0)
where == 0Description
TRUEevaluated 48 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 49 times by 1 test
Evaluated by:
  • timeout
48-49
167 signal (sig, SIG_IGN);
executed 48 times by 1 test: signal (sig, ((__sighandler_t) 1) );
Executed by:
  • timeout
48
168 return kill (where, sig);
executed 97 times by 1 test: return kill (where, sig);
Executed by:
  • timeout
97
169}-
170-
171/* Signal handler which is required for sigsuspend() to be interrupted-
172 whenever SIGCHLD is received. */-
173static void-
174chld (int sig)-
175{-
176}-
177-
178-
179static void-
180cleanup (int sig)-
181{-
182 if (sig == SIGALRM)
sig == 14Description
TRUEevaluated 24 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 1 time by 1 test
Evaluated by:
  • timeout
1-24
183 {-
184 timed_out = 1;-
185 sig = term_signal;-
186 }
executed 24 times by 1 test: end of block
Executed by:
  • timeout
24
187 if (monitored_pid)
monitored_pidDescription
TRUEevaluated 25 times by 1 test
Evaluated by:
  • timeout
FALSEnever evaluated
0-25
188 {-
189 if (kill_after)
kill_afterDescription
TRUEnever evaluated
FALSEevaluated 25 times by 1 test
Evaluated by:
  • timeout
0-25
190 {-
191 int saved_errno = errno; /* settimeout may reset. */-
192 /* Start a new timeout after which we'll send SIGKILL. */-
193 term_signal = SIGKILL;-
194 settimeout (kill_after, false);-
195 kill_after = 0; /* Don't let later signals reset kill alarm. */-
196 errno = saved_errno;-
197 }
never executed: end of block
0
198-
199 /* Send the signal directly to the monitored child,-
200 in case it has itself become group leader,-
201 or is not running in a separate group. */-
202 if (verbose)
verboseDescription
TRUEnever evaluated
FALSEevaluated 25 times by 1 test
Evaluated by:
  • timeout
0-25
203 {-
204 char signame[MAX (SIG2STR_MAX, INT_BUFSIZE_BOUND (int))];-
205 if (sig2str (sig, signame) != 0)
sig2str (sig, signame) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
206 snprintf (signame, sizeof signame, "%d", sig);
never executed: snprintf (signame, sizeof signame, "%d", sig);
0
207 error (0, 0, _("sending signal %s to command %s"),-
208 signame, quote (command));-
209 }
never executed: end of block
0
210 send_sig (monitored_pid, sig);-
211-
212 /* The normal case is the job has remained in our-
213 newly created process group, so send to all processes in that. */-
214 if (!foreground)
!foregroundDescription
TRUEevaluated 24 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 1 time by 1 test
Evaluated by:
  • timeout
1-24
215 {-
216 send_sig (0, sig);-
217 if (sig != SIGKILL && sig != SIGCONT)
sig != 9Description
TRUEevaluated 24 times by 1 test
Evaluated by:
  • timeout
FALSEnever evaluated
sig != 18Description
TRUEevaluated 24 times by 1 test
Evaluated by:
  • timeout
FALSEnever evaluated
0-24
218 {-
219 send_sig (monitored_pid, SIGCONT);-
220 send_sig (0, SIGCONT);-
221 }
executed 24 times by 1 test: end of block
Executed by:
  • timeout
24
222 }
executed 24 times by 1 test: end of block
Executed by:
  • timeout
24
223 }
executed 25 times by 1 test: end of block
Executed by:
  • timeout
25
224 else /* we're the child or the child is not exec'd yet. */-
225 _exit (128 + sig);
never executed: _exit (128 + sig);
0
226}-
227-
228void-
229usage (int status)-
230{-
231 if (status != EXIT_SUCCESS)
status != 0Description
TRUEevaluated 12 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 7 times by 1 test
Evaluated by:
  • timeout
7-12
232 emit_try_help ();
executed 12 times by 1 test: end of block
Executed by:
  • timeout
12
233 else-
234 {-
235 printf (_("\-
236Usage: %s [OPTION] DURATION COMMAND [ARG]...\n\-
237 or: %s [OPTION]\n"), program_name, program_name);-
238-
239 fputs (_("\-
240Start COMMAND, and kill it if still running after DURATION.\n\-
241"), stdout);-
242-
243 emit_mandatory_arg_note ();-
244-
245 fputs (_("\-
246 --preserve-status\n\-
247 exit with the same status as COMMAND, even when the\n\-
248 command times out\n\-
249 --foreground\n\-
250 when not running timeout directly from a shell prompt,\n\-
251 allow COMMAND to read from the TTY and get TTY signals;\n\-
252 in this mode, children of COMMAND will not be timed out\n\-
253 -k, --kill-after=DURATION\n\-
254 also send a KILL signal if COMMAND is still running\n\-
255 this long after the initial signal was sent\n\-
256 -s, --signal=SIGNAL\n\-
257 specify the signal to be sent on timeout;\n\-
258 SIGNAL may be a name like 'HUP' or a number;\n\-
259 see 'kill -l' for a list of signals\n"), stdout);-
260 fputs (_("\-
261 -v, --verbose diagnose to stderr any signal sent upon timeout\n"), stdout);-
262-
263 fputs (HELP_OPTION_DESCRIPTION, stdout);-
264 fputs (VERSION_OPTION_DESCRIPTION, stdout);-
265-
266 fputs (_("\n\-
267DURATION is a floating point number with an optional suffix:\n\-
268's' for seconds (the default), 'm' for minutes, 'h' for hours \-
269or 'd' for days.\n"), stdout);-
270-
271 fputs (_("\n\-
272If the command times out, and --preserve-status is not set, then exit with\n\-
273status 124. Otherwise, exit with the status of COMMAND. If no signal\n\-
274is specified, send the TERM signal upon timeout. The TERM signal kills\n\-
275any process that does not block or catch that signal. It may be necessary\n\-
276to use the KILL (9) signal, since this signal cannot be caught, in which\n\-
277case the exit status is 128+9 rather than 124.\n"), stdout);-
278 emit_ancillary_info (PROGRAM_NAME);-
279 }
executed 7 times by 1 test: end of block
Executed by:
  • timeout
7
280 exit (status);
executed 19 times by 1 test: exit (status);
Executed by:
  • timeout
19
281}-
282-
283/* Given a floating point value *X, and a suffix character, SUFFIX_CHAR,-
284 scale *X by the multiplier implied by SUFFIX_CHAR. SUFFIX_CHAR may-
285 be the NUL byte or 's' to denote seconds, 'm' for minutes, 'h' for-
286 hours, or 'd' for days. If SUFFIX_CHAR is invalid, don't modify *X-
287 and return false. Otherwise return true. */-
288-
289static bool-
290apply_time_suffix (double *x, char suffix_char)-
291{-
292 int multiplier;-
293-
294 switch (suffix_char)-
295 {-
296 case 0:
executed 131 times by 1 test: case 0:
Executed by:
  • timeout
131
297 case 's':
executed 11 times by 1 test: case 's':
Executed by:
  • timeout
11
298 multiplier = 1;-
299 break;
executed 142 times by 1 test: break;
Executed by:
  • timeout
142
300 case 'm':
never executed: case 'm':
0
301 multiplier = 60;-
302 break;
never executed: break;
0
303 case 'h':
never executed: case 'h':
0
304 multiplier = 60 * 60;-
305 break;
never executed: break;
0
306 case 'd':
executed 3 times by 1 test: case 'd':
Executed by:
  • timeout
3
307 multiplier = 60 * 60 * 24;-
308 break;
executed 3 times by 1 test: break;
Executed by:
  • timeout
3
309 default:
executed 1 time by 1 test: default:
Executed by:
  • timeout
1
310 return false;
executed 1 time by 1 test: return 0 ;
Executed by:
  • timeout
1
311 }-
312-
313 *x *= multiplier;-
314-
315 return true;
executed 145 times by 1 test: return 1 ;
Executed by:
  • timeout
145
316}-
317-
318static double-
319parse_duration (const char* str)-
320{-
321 double duration;-
322 const char *ep;-
323-
324 if (! (xstrtod (str, &ep, &duration, c_strtod) || errno == ERANGE)
xstrtod (str, ...ion, c_strtod)Description
TRUEevaluated 145 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 6 times by 1 test
Evaluated by:
  • timeout
(*__errno_location ()) == 34Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 4 times by 1 test
Evaluated by:
  • timeout
2-145
325 /* Nonnegative interval. */-
326 || ! (0 <= duration)
! (0 <= duration)Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • timeout
FALSEevaluated 146 times by 1 test
Evaluated by:
  • timeout
1-146
327 /* No extra chars after the number and an optional s,m,h,d char. */-
328 || (*ep && *(ep + 1))
*epDescription
TRUEevaluated 15 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 131 times by 1 test
Evaluated by:
  • timeout
*(ep + 1)Description
TRUEnever evaluated
FALSEevaluated 15 times by 1 test
Evaluated by:
  • timeout
0-131
329 /* Check any suffix char and update timeout based on the suffix. */-
330 || !apply_time_suffix (&duration, *ep))
!apply_time_su...duration, *ep)Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • timeout
FALSEevaluated 145 times by 1 test
Evaluated by:
  • timeout
1-145
331 {-
332 error (0, 0, _("invalid time interval %s"), quote (str));-
333 usage (EXIT_CANCELED);-
334 }
never executed: end of block
0
335-
336 return duration;
executed 145 times by 1 test: return duration;
Executed by:
  • timeout
145
337}-
338-
339static void-
340unblock_signal (int sig)-
341{-
342 sigset_t unblock_set;-
343 sigemptyset (&unblock_set);-
344 sigaddset (&unblock_set, sig);-
345 if (sigprocmask (SIG_UNBLOCK, &unblock_set, NULL) != 0)
sigprocmask ( ...id *)0) ) != 0Description
TRUEnever evaluated
FALSEevaluated 288 times by 1 test
Evaluated by:
  • timeout
0-288
346 error (0, errno, _("warning: sigprocmask"));
never executed: error (0, (*__errno_location ()) , dcgettext (((void *)0), "warning: sigprocmask" , 5) );
0
347}
executed 288 times by 1 test: end of block
Executed by:
  • timeout
288
348-
349static void-
350install_sigchld (void)-
351{-
352 struct sigaction sa;-
353 sigemptyset (&sa.sa_mask); /* Allow concurrent calls to handler */-
354 sa.sa_handler = chld;-
355 sa.sa_flags = SA_RESTART; /* Restart syscalls if possible, as that's-
356 more likely to work cleanly. */-
357-
358 sigaction (SIGCHLD, &sa, NULL);-
359-
360 /* We inherit the signal mask from our parent process,-
361 so ensure SIGCHLD is not blocked. */-
362 unblock_signal (SIGCHLD);-
363}
executed 145 times by 1 test: end of block
Executed by:
  • timeout
145
364-
365static void-
366install_cleanup (int sigterm)-
367{-
368 struct sigaction sa;-
369 sigemptyset (&sa.sa_mask); /* Allow concurrent calls to handler */-
370 sa.sa_handler = cleanup;-
371 sa.sa_flags = SA_RESTART; /* Restart syscalls if possible, as that's-
372 more likely to work cleanly. */-
373-
374 sigaction (SIGALRM, &sa, NULL); /* our timeout. */-
375 sigaction (SIGINT, &sa, NULL); /* Ctrl-C at terminal for example. */-
376 sigaction (SIGQUIT, &sa, NULL); /* Ctrl-\ at terminal for example. */-
377 sigaction (SIGHUP, &sa, NULL); /* terminal closed for example. */-
378 sigaction (SIGTERM, &sa, NULL); /* if we're killed, stop monitored proc. */-
379 sigaction (sigterm, &sa, NULL); /* user specified termination signal. */-
380}
executed 145 times by 1 test: end of block
Executed by:
  • timeout
145
381-
382/* Block all signals which were registered with cleanup() as the signal-
383 handler, so we never kill processes after waitpid() returns.-
384 Also block SIGCHLD to ensure it doesn't fire between-
385 waitpid() polling and sigsuspend() waiting for a signal.-
386 Return original mask in OLD_SET. */-
387static void-
388block_cleanup_and_chld (int sigterm, sigset_t *old_set)-
389{-
390 sigset_t block_set;-
391 sigemptyset (&block_set);-
392-
393 sigaddset (&block_set, SIGALRM);-
394 sigaddset (&block_set, SIGINT);-
395 sigaddset (&block_set, SIGQUIT);-
396 sigaddset (&block_set, SIGHUP);-
397 sigaddset (&block_set, SIGTERM);-
398 sigaddset (&block_set, sigterm);-
399-
400 sigaddset (&block_set, SIGCHLD);-
401-
402 if (sigprocmask (SIG_BLOCK, &block_set, old_set) != 0)
sigprocmask ( ... old_set) != 0Description
TRUEnever evaluated
FALSEevaluated 143 times by 1 test
Evaluated by:
  • timeout
0-143
403 error (0, errno, _("warning: sigprocmask"));
never executed: error (0, (*__errno_location ()) , dcgettext (((void *)0), "warning: sigprocmask" , 5) );
0
404}
executed 143 times by 1 test: end of block
Executed by:
  • timeout
143
405-
406/* Try to disable core dumps for this process.-
407 Return TRUE if successful, FALSE otherwise. */-
408static bool-
409disable_core_dumps (void)-
410{-
411#if HAVE_PRCTL && defined PR_SET_DUMPABLE-
412 if (prctl (PR_SET_DUMPABLE, 0) == 0)
prctl ( 4 , 0) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
413 return true;
never executed: return 1 ;
0
414-
415#elif HAVE_SETRLIMIT && defined RLIMIT_CORE-
416 /* Note this doesn't disable processing by a filter in-
417 /proc/sys/kernel/core_pattern on Linux. */-
418 if (setrlimit (RLIMIT_CORE, &(struct rlimit) {0,0}) == 0)-
419 return true;-
420-
421#else-
422 return false;-
423#endif-
424-
425 error (0, errno, _("warning: disabling core dumps failed"));-
426 return false;
never executed: return 0 ;
0
427}-
428-
429int-
430main (int argc, char **argv)-
431{-
432 double timeout;-
433 char signame[SIG2STR_MAX];-
434 int c;-
435-
436 initialize_main (&argc, &argv);-
437 set_program_name (argv[0]);-
438 setlocale (LC_ALL, "");-
439 bindtextdomain (PACKAGE, LOCALEDIR);-
440 textdomain (PACKAGE);-
441-
442 initialize_exit_failure (EXIT_CANCELED);-
443 atexit (close_stdout);-
444-
445 while ((c = getopt_long (argc, argv, "+k:s:v", long_options, NULL)) != -1)
(c = getopt_lo... *)0) )) != -1Description
TRUEevaluated 32 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 148 times by 1 test
Evaluated by:
  • timeout
32-148
446 {-
447 switch (c)-
448 {-
449 case 'k':
executed 3 times by 1 test: case 'k':
Executed by:
  • timeout
3
450 kill_after = parse_duration (optarg);-
451 break;
never executed: break;
0
452-
453 case 's':
executed 5 times by 1 test: case 's':
Executed by:
  • timeout
5
454 term_signal = operand2sig (optarg, signame);-
455 if (term_signal == -1)
term_signal == -1Description
TRUEevaluated 3 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 2 times by 1 test
Evaluated by:
  • timeout
2-3
456 usage (EXIT_CANCELED);
executed 3 times by 1 test: usage (EXIT_CANCELED);
Executed by:
  • timeout
3
457 break;
executed 2 times by 1 test: break;
Executed by:
  • timeout
2
458-
459 case 'v':
executed 2 times by 1 test: case 'v':
Executed by:
  • timeout
2
460 verbose = true;-
461 break;
executed 2 times by 1 test: break;
Executed by:
  • timeout
2
462-
463 case FOREGROUND_OPTION:
executed 2 times by 1 test: case FOREGROUND_OPTION:
Executed by:
  • timeout
2
464 foreground = true;-
465 break;
executed 2 times by 1 test: break;
Executed by:
  • timeout
2
466-
467 case PRESERVE_STATUS_OPTION:
executed 2 times by 1 test: case PRESERVE_STATUS_OPTION:
Executed by:
  • timeout
2
468 preserve_status = true;-
469 break;
executed 2 times by 1 test: break;
Executed by:
  • timeout
2
470-
471 case_GETOPT_HELP_CHAR;
never executed: break;
executed 7 times by 1 test: case GETOPT_HELP_CHAR:
Executed by:
  • timeout
0-7
472-
473 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
executed 8 times by 1 test: exit ( 0 );
Executed by:
  • timeout
never executed: break;
executed 8 times by 1 test: case GETOPT_VERSION_CHAR:
Executed by:
  • timeout
0-8
474-
475 default:
executed 3 times by 1 test: default:
Executed by:
  • timeout
3
476 usage (EXIT_CANCELED);-
477 break;
never executed: break;
0
478 }-
479 }-
480-
481 if (argc - optind < 2)
argc - optind < 2Description
TRUEnever evaluated
FALSEevaluated 148 times by 1 test
Evaluated by:
  • timeout
0-148
482 usage (EXIT_CANCELED);
never executed: usage (EXIT_CANCELED);
0
483-
484 timeout = parse_duration (argv[optind++]);-
485-
486 argv += optind;-
487 command = argv[0];-
488-
489 /* Ensure we're in our own group so all subprocesses can be killed.-
490 Note we don't just put the child in a separate group as-
491 then we would need to worry about foreground and background groups-
492 and propagating signals between them. */-
493 if (!foreground)
!foregroundDescription
TRUEevaluated 144 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 1 time by 1 test
Evaluated by:
  • timeout
1-144
494 setpgid (0, 0);
executed 144 times by 1 test: setpgid (0, 0);
Executed by:
  • timeout
144
495-
496 /* Setup handlers before fork() so that we-
497 handle any signals caused by child, without races. */-
498 install_cleanup (term_signal);-
499 signal (SIGTTIN, SIG_IGN); /* Don't stop if background child needs tty. */-
500 signal (SIGTTOU, SIG_IGN); /* Don't stop if background child needs tty. */-
501 install_sigchld (); /* Interrupt sigsuspend() when child exits. */-
502-
503 monitored_pid = fork ();-
504 if (monitored_pid == -1)
monitored_pid == -1Description
TRUEnever evaluated
FALSEevaluated 145 times by 1 test
Evaluated by:
  • timeout
0-145
505 {-
506 error (0, errno, _("fork system call failed"));-
507 return EXIT_CANCELED;
never executed: return EXIT_CANCELED;
0
508 }-
509 else if (monitored_pid == 0)
monitored_pid == 0Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 143 times by 1 test
Evaluated by:
  • timeout
2-143
510 { /* child */-
511 /* exec doesn't reset SIG_IGN -> SIG_DFL. */-
512 signal (SIGTTIN, SIG_DFL);-
513 signal (SIGTTOU, SIG_DFL);-
514-
515 execvp (argv[0], argv); /* FIXME: should we use "sh -c" ... here? */-
516-
517 /* exit like sh, env, nohup, ... */-
518 int exit_status = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE;
(*__errno_location ()) == 2Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • timeout
FALSEevaluated 1 time by 1 test
Evaluated by:
  • timeout
1
519 error (0, errno, _("failed to run command %s"), quote (command));-
520 return exit_status;
executed 2 times by 1 test: return exit_status;
Executed by:
  • timeout
2
521 }-
522 else-
523 {-
524 pid_t wait_result;-
525 int status;-
526-
527 /* We configure timers so that SIGALRM is sent on expiry.-
528 Therefore ensure we don't inherit a mask blocking SIGALRM. */-
529 unblock_signal (SIGALRM);-
530-
531 settimeout (timeout, true);-
532-
533 /* Ensure we don't cleanup() after waitpid() reaps the child,-
534 to avoid sending signals to a possibly different process. */-
535 sigset_t cleanup_set;-
536 block_cleanup_and_chld (term_signal, &cleanup_set);-
537-
538 while ((wait_result = waitpid (monitored_pid, &status, WNOHANG)) == 0)
(wait_result =...tus, 1 )) == 0Description
TRUEevaluated 169 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 143 times by 1 test
Evaluated by:
  • timeout
143-169
539 sigsuspend (&cleanup_set); /* Wait with cleanup signals unblocked. */
executed 169 times by 1 test: sigsuspend (&cleanup_set);
Executed by:
  • timeout
169
540-
541 if (wait_result < 0)
wait_result < 0Description
TRUEnever evaluated
FALSEevaluated 143 times by 1 test
Evaluated by:
  • timeout
0-143
542 {-
543 /* shouldn't happen. */-
544 error (0, errno, _("error waiting for command"));-
545 status = EXIT_CANCELED;-
546 }
never executed: end of block
0
547 else-
548 {-
549 if (WIFEXITED (status))
((( status ) & 0x7f) == 0)Description
TRUEevaluated 121 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 22 times by 1 test
Evaluated by:
  • timeout
22-121
550 status = WEXITSTATUS (status);
executed 121 times by 1 test: status = ((( status ) & 0xff00) >> 8) ;
Executed by:
  • timeout
121
551 else if (WIFSIGNALED (status))
(((signed char... 1) >> 1) > 0)Description
TRUEevaluated 22 times by 1 test
Evaluated by:
  • timeout
FALSEnever evaluated
0-22
552 {-
553 int sig = WTERMSIG (status);-
554 if (WCOREDUMP (status))
(( status ) & 0x80)Description
TRUEnever evaluated
FALSEevaluated 22 times by 1 test
Evaluated by:
  • timeout
0-22
555 error (0, 0, _("the monitored command dumped core"));
never executed: error (0, 0, dcgettext (((void *)0), "the monitored command dumped core" , 5) );
0
556 if (!timed_out && disable_core_dumps ())
!timed_outDescription
TRUEnever evaluated
FALSEevaluated 22 times by 1 test
Evaluated by:
  • timeout
disable_core_dumps ()Description
TRUEnever evaluated
FALSEnever evaluated
0-22
557 {-
558 /* exit with the signal flag set. */-
559 signal (sig, SIG_DFL);-
560 unblock_signal (sig);-
561 raise (sig);-
562 }
never executed: end of block
0
563 status = sig + 128; /* what sh returns for signaled processes. */-
564 }
executed 22 times by 1 test: end of block
Executed by:
  • timeout
22
565 else-
566 {-
567 /* shouldn't happen. */-
568 error (0, 0, _("unknown status from command (%d)"), status);-
569 status = EXIT_FAILURE;-
570 }
never executed: end of block
0
571 }-
572-
573 if (timed_out && !preserve_status)
timed_outDescription
TRUEevaluated 24 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 119 times by 1 test
Evaluated by:
  • timeout
!preserve_statusDescription
TRUEevaluated 23 times by 1 test
Evaluated by:
  • timeout
FALSEevaluated 1 time by 1 test
Evaluated by:
  • timeout
1-119
574 status = EXIT_TIMEDOUT;
executed 23 times by 1 test: status = EXIT_TIMEDOUT;
Executed by:
  • timeout
23
575 return status;
executed 143 times by 1 test: return status;
Executed by:
  • timeout
143
576 }-
577}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2