- for (;;) {
- ssize_t rcode;
-
- FD_ZERO(&readfds);
- max_fd = 0;
-
- /*
- * Loop over all the listening FD's.
- */
- for (listener = mainconfig.listen;
- listener != NULL;
- listener = listener->next) {
- if (listener->fd < 0) continue;
-
- if (!read_from_detail &&
- (listener->type == RAD_LISTEN_DETAIL)) continue;
-
- FD_SET(listener->fd, &readfds);
- if (listener->fd > max_fd) max_fd = listener->fd;
- }
-
- /*
- * Add in the self pipe FD, for signals or
- * notices from the child threads.
- */
- FD_SET(radius_self_pipe[0], &readfds);
- if (radius_self_pipe[0] > max_fd) {
- max_fd = radius_self_pipe[0];
- }
-
- if (!ptv) {
- DEBUG2("Nothing to do. Sleeping until we see a request.");
- } else if (tv.tv_sec) {
- DEBUG2("Waking up in %d seconds...",
- (int) tv.tv_sec);
- }
-
- status = select(max_fd + 1, &readfds, NULL, NULL, ptv);
- if ((status < 0) && (errno != EINTR)) {
- radlog(L_ERR, "Unexpected error in select(): %s",
- strerror(errno));
- exit(1);
- }
- time_now = time(NULL);
-
-#ifndef HAVE_PTHREAD_H
- /*
- * If there are no child threads, then there may
- * be child processes. In that case, wait for
- * their exit status, and throw that exit status
- * away. This helps get rid of zxombie children.
- */
- while (waitpid(-1, &argval, WNOHANG) > 0) {
- /* do nothing */
- }
-#endif
-
- /*
- * Before doing anything else, check the self pipe.
- */
- if (FD_ISSET(radius_self_pipe[0], &readfds) &&
- (rcode = read(radius_self_pipe[0], buffer, sizeof(buffer))) > 0) {
- ssize_t i;
-
- for (i = 1; i < rcode; i++) {
- buffer[0] |= buffer[i];
- }
-
- if ((buffer[0] & (RADIUS_SIGNAL_SELF_EXIT | RADIUS_SIGNAL_SELF_TERM)) != 0) {
- DEBUG("Exiting...");
-
- /*
- * Ignore the TERM signal: we're
- * about to die.
- */
- signal(SIGTERM, SIG_IGN);
-
- /*
- * Send a TERM signal to all
- * associated processes
- * (including us, which gets
- * ignored.)
- */
- kill(-radius_pid, SIGTERM);
-
- /*
- * FIXME: Kill child threads, and
- * clean up?
- */
-
- /*
- * FIXME: clean up any active REQUEST
- * handles.
- */
-
- /*
- * We're exiting, so we can delete the PID
- * file. (If it doesn't exist, we can ignore
- * the error returned by unlink)
- */
- if (dont_fork == FALSE) {
- unlink(mainconfig.pid_file);
- }
-
- radius_event_free();
-
- /*
- * Free the configuration items.
- */
- free_mainconfig();
-
- /*
- * Detach any modules.
- */
- detach_modules();
-
- free(radius_dir);
-
- /*
- * SIGTERM gets do_exit=0,
- * and we want to exit cleanly.
- *
- * Other signals make us exit
- * with an error status.
- */
- if ((buffer[0] & RADIUS_SIGNAL_SELF_EXIT) != 0) {
- exit(1);
- }
- exit(0);
- } /* else exit/term flags weren't set */
-
- if ((buffer[0] & RADIUS_SIGNAL_SELF_HUP) != 0) {
- DEBUG("Received HUP signal");
-#ifdef HAVE_PTHREAD_H
- /*
- * Threads: wait for all threads to stop
- * processing before re-loading the
- * config, so we don't pull the rug out
- * from under them.
- */
- int max_wait = 0;
- if (spawn_flag) for(;;) {
- /*
- * Block until there are
- * zero threads with a
- * REQUEST handle.
- *
- * FIXME: Wait for
- * threads to send us a
- * signal in the pipe?
- */
- sig_hup_block = TRUE;
-
- if( (total_active_threads() == 0) ||
- (max_wait >= 5) ) {
- sig_hup_block = FALSE;
- break;
- }
- sleep(1);
- max_wait++;
- }
-#endif