1/*++ 2/* NAME 3/* timed_wait 3 4/* SUMMARY 5/* wait operations with timeout 6/* SYNOPSIS 7/* #include <timed_wait.h> 8/* 9/* int timed_waitpid(pid, statusp, options, time_limit) 10/* pid_t pid; 11/* WAIT_STATUS_T *statusp; 12/* int options; 13/* int time_limit; 14/* DESCRIPTION 15/* \fItimed_waitpid\fR() waits at most \fItime_limit\fR seconds 16/* for process termination. 17/* 18/* Arguments: 19/* .IP "pid, statusp, options" 20/* The process ID, status pointer and options passed to waitpid(3). 21/* .IP time_limit 22/* The time in seconds that timed_waitpid() will wait. 23/* This must be a number > 0. 24/* DIAGNOSTICS 25/* Panic: interface violation. 26/* 27/* When the time limit is exceeded, the result is -1 and errno 28/* is set to ETIMEDOUT. Otherwise, the result value is the result 29/* from the underlying waitpid() routine. 30/* BUGS 31/* If there were a \fIportable\fR way to select() on process status 32/* information, these routines would not have to use a steenkeeng 33/* alarm() timer and signal() handler. 34/* LICENSE 35/* .ad 36/* .fi 37/* The Secure Mailer license must be distributed with this software. 38/* AUTHOR(S) 39/* Wietse Venema 40/* IBM T.J. Watson Research 41/* P.O. Box 704 42/* Yorktown Heights, NY 10598, USA 43/*--*/ 44 45/* System library. */ 46 47#include <sys_defs.h> 48#include <sys/wait.h> 49#include <unistd.h> 50#include <signal.h> 51#include <errno.h> 52 53/* Utility library. */ 54 55#include <msg.h> 56#include <posix_signals.h> 57#include <timed_wait.h> 58 59/* Application-specific. */ 60 61static int timed_wait_expired; 62 63/* timed_wait_alarm - timeout handler */ 64 65static void timed_wait_alarm(int unused_sig) 66{ 67 68 /* 69 * WARNING WARNING WARNING. 70 * 71 * This code runs at unpredictable moments, as a signal handler. This code 72 * is here only so that we can break out of waitpid(). Don't put any code 73 * here other than for setting a global flag. 74 */ 75 timed_wait_expired = 1; 76} 77 78/* timed_waitpid - waitpid with time limit */ 79 80int timed_waitpid(pid_t pid, WAIT_STATUS_T *statusp, int options, 81 int time_limit) 82{ 83 const char *myname = "timed_waitpid"; 84 struct sigaction action; 85 struct sigaction old_action; 86 int time_left; 87 int wpid; 88 89 /* 90 * Sanity checks. 91 */ 92 if (time_limit <= 0) 93 msg_panic("%s: bad time limit: %d", myname, time_limit); 94 95 /* 96 * Set up a timer. 97 */ 98 sigemptyset(&action.sa_mask); 99 action.sa_flags = 0; 100 action.sa_handler = timed_wait_alarm; 101 if (sigaction(SIGALRM, &action, &old_action) < 0) 102 msg_fatal("%s: sigaction(SIGALRM): %m", myname); 103 timed_wait_expired = 0; 104 time_left = alarm(time_limit); 105 106 /* 107 * Wait for only a limited amount of time. 108 */ 109 if ((wpid = waitpid(pid, statusp, options)) < 0 && timed_wait_expired) 110 errno = ETIMEDOUT; 111 112 /* 113 * Cleanup. 114 */ 115 alarm(0); 116 if (sigaction(SIGALRM, &old_action, (struct sigaction *) 0) < 0) 117 msg_fatal("%s: sigaction(SIGALRM): %m", myname); 118 if (time_left) 119 alarm(time_left); 120 121 return (wpid); 122} 123