168
* We don't want to catch SIGCHLD for a host of reasons.
170
* - exec_wait means that someone, somewhere, somewhen, will
171
* call waitpid(), and catch the child.
173
* - SIGCHLD is delivered to a random thread, not the one that
176
* - if another thread catches the child, we have to coordinate
177
* with the thread doing the waiting.
179
* - if we don't waitpid() for non-wait children, they'll be zombies,
180
* and will hang around forever.
183
static void reap_children(void)
185
if (thread_pool.wait_head != thread_pool.wait_tail) {
188
pthread_mutex_lock(&thread_pool.wait_mutex);
189
for (num = ((thread_pool.wait_tail + MAX_WAITERS) - thread_pool.wait_head) % MAX_WAITERS;
192
pid_t pid = thread_pool.wait[thread_pool.wait_head];
194
thread_pool.wait_head++;
195
thread_pool.wait_head %= MAX_WAITERS;
198
* Child is still alive: move it to the tail.
200
if (waitpid(pid, NULL, WNOHANG) == 0) {
201
if (((thread_pool.wait_tail + 1) % MAX_WAITERS)
202
== thread_pool.wait_head) {
206
thread_pool.wait[thread_pool.wait_tail] = pid;
207
thread_pool.wait_tail++;
208
thread_pool.wait_tail %= MAX_WAITERS;
209
} /* else no child, or was already reaped */
211
pthread_mutex_unlock(&thread_pool.wait_mutex);
167
217
* Add a request to the list of waiting requests.
168
218
* This function gets called ONLY from the main handler thread...
170
220
* This function should never fail.
172
static void request_enqueue(REQUEST *request, RAD_REQUEST_FUNP fun)
222
static int request_enqueue(REQUEST *request, RAD_REQUEST_FUNP fun)
926
static int exec_initialized = FALSE;
929
* Initialize the stuff for keeping track of child processes.
931
void rad_exec_init(void)
936
* Initialize the mutex used to remember calls to fork.
938
pthread_mutex_init(&fork_mutex, NULL);
941
* Initialize the data structure where we remember the
942
* mappings of thread ID && child PID to exit status.
944
for (i = 0; i < NUM_FORKERS; i++) {
945
forkers[i].thread_id = NO_SUCH_CHILD_PID;
946
forkers[i].child_pid = -1;
947
forkers[i].status = 0;
950
exec_initialized = TRUE;
954
* We use the PID number as a base for the array index, so that
955
* we can quickly turn the PID into a free array entry, instead
956
* of rooting blindly through the entire array.
958
#define PID_2_ARRAY(pid) (((int) pid ) & (NUM_FORKERS - 1))
961
983
* Thread wrapper for fork().
963
985
pid_t rad_fork(int exec_wait)
969
* The thread is NOT interested in waiting for the exit
970
* status of the child process, so we don't bother
971
* updating our kludgy array.
973
* Or, there no NO threads, so we can just do the fork
976
if (!exec_wait || !exec_initialized) {
989
if (exec_wait) return fork();
992
* Ensure that children are reaped always.
999
pthread_mutex_lock(&thread_pool.wait_mutex);
1002
* No room to save the PID: die.
1004
if (((thread_pool.wait_tail + 1) % MAX_WAITERS)
1005
== thread_pool.wait_head) {
981
* Block SIGCLHD until such time as we've saved the PID.
983
* Note that we block SIGCHLD for ALL threads associated
984
* with this process! This is to prevent race conditions!
987
sigaddset(&set, SIGCHLD);
988
sigprocmask(SIG_BLOCK, &set, NULL);
1010
* Fork & save the PID for later reaping.
993
1012
child_pid = fork();
996
* We managed to fork. Let's see if we have a free
999
if (child_pid > 0) { /* parent */
1002
time_t now = time(NULL);
1005
* We store the information in the array
1006
* indexed by PID. This means that we have
1007
* on average an O(1) lookup to find the element,
1008
* instead of rooting through the entire array.
1010
i = PID_2_ARRAY(child_pid);
1014
* We may have multiple threads trying to find an
1015
* empty position, so we lock the array until
1016
* we've found an entry.
1018
pthread_mutex_lock(&fork_mutex);
1020
if (forkers[i].thread_id == NO_SUCH_CHILD_PID) {
1026
* Clean up any stale forked sessions.
1028
* This sometimes happens, for crazy reasons.
1030
if ((now - forkers[i].time_forked) > 30) {
1031
forkers[i].thread_id = NO_SUCH_CHILD_PID;
1034
* Grab the child's exit condition,
1037
waitpid(forkers[i].child_pid,
1040
sem_destroy(&forkers[i].child_done);
1046
* Increment it, within the array.
1049
i &= (NUM_FORKERS - 1);
1050
} while (i != PID_2_ARRAY(child_pid));
1053
* Arg. We did a fork, and there was nowhere to
1057
sigprocmask(SIG_UNBLOCK, &set, NULL);
1058
pthread_mutex_unlock(&fork_mutex);
1063
* In the parent, set the status, and create the
1066
forkers[found].status = -1;
1067
forkers[found].child_pid = child_pid;
1068
forkers[found].thread_id = pthread_self();
1069
forkers[found].time_forked = now;
1070
sem_init(&forkers[found].child_done, 0, SEMAPHORE_LOCKED);
1071
pthread_mutex_unlock(&fork_mutex);
1013
if (child_pid != 0) {
1014
thread_pool.wait[thread_pool.wait_tail] = child_pid;
1015
thread_pool.wait_tail++;
1016
thread_pool.wait_tail %= MAX_WAITERS;
1021
pthread_mutex_unlock(&thread_pool.wait_mutex);
1075
* Unblock SIGCHLD, now that there's no chance of bad entries
1078
sigprocmask(SIG_UNBLOCK, &set, NULL);
1081
1025
* Return whatever we were told.
1083
1027
return child_pid;
1087
* Thread wrapper for waitpid(), so threads can wait for
1088
* the PID they forked.
1032
* We may not need this any more...
1090
1034
pid_t rad_waitpid(pid_t pid, int *status, int options)
1094
pthread_t self = pthread_self();
1097
* We're only allowed to wait for a SPECIFIC pid.
1104
* Find the PID to wait for, starting at an index within
1105
* the array. This makes the lookups O(1) on average,
1106
* instead of O(n), when the array is filling up.
1109
i = PID_2_ARRAY(pid);
1112
* We were the ones who forked this specific
1115
if ((forkers[i].thread_id == self) &&
1116
(forkers[i].child_pid == pid)) {
1122
i &= (NUM_FORKERS - 1);
1123
} while (i != PID_2_ARRAY(pid));
1126
* No thread ID found: we're trying to wait for a child
1127
* we've never forked!
1134
* Wait for the signal that the child's status has been
1137
if (options == WNOHANG) {
1138
rcode = sem_trywait(&forkers[found].child_done);
1140
return 0; /* no child available */
1142
} else { /* wait forever */
1144
rcode = sem_wait(&forkers[found].child_done);
1145
if ((rcode != 0) && (errno == EINTR)) {
1151
* We've got the semaphore. Now destroy it.
1153
* FIXME: Maybe we want to set up the semaphores in advance,
1154
* to prevent the creation && deletion of lots of them,
1155
* if creating and deleting them is expensive.
1157
sem_destroy(&forkers[found].child_done);
1160
* Save the status BEFORE we re-set the thread ID.
1162
*status = forkers[found].status;
1165
* This next line taints the other array entries,
1166
* due to other threads re-using the data structure.
1168
forkers[found].thread_id = NO_SUCH_CHILD_PID;
1174
* Called by the main signal handler, to save the status of the child
1176
int rad_savepid(pid_t pid, int status)
1181
* Find the PID to wait for, starting at an index within
1182
* the array. This makes the lookups O(1) on average,
1183
* instead of O(n), when the array is filling up.
1185
i = PID_2_ARRAY(pid);
1188
* Do NOT lock the array, as nothing else sets the
1189
* status and posts the semaphore.
1193
* Any thread can get the sigchild...
1195
if ((forkers[i].thread_id != NO_SUCH_CHILD_PID) &&
1196
(forkers[i].child_pid == pid)) {
1198
* Save the status, THEN post the
1201
forkers[i].status = status;
1202
sem_post(&forkers[i].child_done);
1205
* FIXME: If the child is more than 60
1206
* seconds out of date, then delete it.
1208
* That is, we've forked, and the forker
1209
* is waiting nearly forever
1215
i &= (NUM_FORKERS - 1);
1216
} while (i != PID_2_ARRAY(pid));
1036
reap_children(); /* be nice to non-wait thingies */
1037
return waitpid(pid, status, options);