Postfix3.3.1
timed_wait.c
[詳解]
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 
61 static int timed_wait_expired;
62 
63 /* timed_wait_alarm - timeout handler */
64 
65 static 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 
80 int 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 }
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
int timed_waitpid(pid_t pid, WAIT_STATUS_T *statusp, int options, int time_limit)
Definition: timed_wait.c:80
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
int WAIT_STATUS_T
Definition: sys_defs.h:1436