/** * Exit regulary on a specific signal. * This is good for profiling which only works if exited regularly * and not by default signal handlers * \param signo The signal that should be handled */ static void sig_usr(int signo) { int status; pid_t pid; UNUSED(pid); if (is_main){ if (sig_flag==0) sig_flag=signo; else /* previous sig. not processed yet, ignoring? */ return; ; if (dont_fork) /* only one proc, doing everything from the sig handler, unsafe, but this is only for debugging mode*/ handle_sigs(); }else{ /* process the important signals */ switch(signo){ case SIGPIPE: LM_INFO("signal %d received\n", signo); break; case SIGINT: case SIGTERM: LM_INFO("signal %d received\n", signo); /* print memory stats for non-main too */ #ifdef PKG_MALLOC LM_GEN1(memdump, "Memory status (pkg):\n"); pkg_status(); #endif exit(0); break; case SIGUSR1: /* statistics -> show only pkg mem */ #ifdef PKG_MALLOC LM_GEN1(memdump, "Memory status (pkg):\n"); pkg_status(); #endif break; case SIGUSR2: #ifdef PKG_MALLOC set_pkg_stats( get_pkg_status_holder(process_no) ); #endif break; case SIGHUP: /* ignored*/ break; case SIGCHLD: pid = waitpid(-1, &status, WNOHANG); LM_DBG("SIGCHLD received from %ld (status=%d), ignoring\n", (long)pid,status); } } }
/** * Signal handler for the server. */ void handle_sigs(void) { pid_t chld; int chld_status; int i; int do_exit; const unsigned int shutdown_time = 60; /* one minute close timeout */ switch(sig_flag){ case 0: break; /* do nothing*/ case SIGPIPE: /* SIGPIPE might be rarely received on use of exec module; simply ignore it */ LM_WARN("SIGPIPE received and ignored\n"); break; case SIGINT: case SIGTERM: /* we end the program in all these cases */ if (sig_flag==SIGINT) LM_DBG("INT received, program terminates\n"); else LM_DBG("SIGTERM received, program terminates\n"); /* first of all, kill the children also */ kill_all_children(SIGTERM); if (signal(SIGALRM, sig_alarm_kill) == SIG_ERR ) { LM_ERR("could not install SIGALARM handler\n"); /* continue, the process will die anyway if no * alarm is installed which is exactly what we want */ } alarm(shutdown_time); while(wait(0) > 0); /* Wait for all the children to terminate */ signal(SIGALRM, sig_alarm_abort); cleanup(1); /* cleanup & show status*/ alarm(0); signal(SIGALRM, SIG_IGN); dprint("Thank you for flying " NAME "\n"); exit(0); break; case SIGUSR1: #ifdef PKG_MALLOC LM_GEN1(memdump, "Memory status (pkg):\n"); pkg_status(); #endif #ifdef SHM_MEM LM_GEN1(memdump, "Memory status (shm):\n"); shm_status(); #endif break; case SIGUSR2: #ifdef PKG_MALLOC set_pkg_stats( get_pkg_status_holder(process_no) ); #endif break; case SIGCHLD: do_exit = 0; while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) { /* is it a process we know about? */ for( i=0 ; i<counted_processes ; i++ ) if (pt[i].pid==chld) break; if (i==counted_processes) { LM_DBG("unkown child process %d ended. Ignoring\n",chld); continue; } do_exit = 1; /* process the signal */ if (WIFEXITED(chld_status)) LM_INFO("child process %d exited normally," " status=%d\n", chld, WEXITSTATUS(chld_status)); else if (WIFSIGNALED(chld_status)) { LM_INFO("child process %d exited by a signal" " %d\n", chld, WTERMSIG(chld_status)); #ifdef WCOREDUMP LM_INFO("core was %sgenerated\n", WCOREDUMP(chld_status) ? "" : "not " ); #endif }else if (WIFSTOPPED(chld_status)) LM_INFO("child process %d stopped by a" " signal %d\n", chld, WSTOPSIG(chld_status)); } if (!do_exit) break; LM_INFO("terminating due to SIGCHLD\n"); /* exit */ kill_all_children(SIGTERM); if (signal(SIGALRM, sig_alarm_kill) == SIG_ERR ) { LM_ERR("could not install SIGALARM handler\n"); /* continue, the process will die anyway if no * alarm is installed which is exactly what we want */ } alarm(shutdown_time); while(wait(0) > 0); /* wait for all the children to terminate*/ signal(SIGALRM, sig_alarm_abort); cleanup(1); /* cleanup & show status*/ alarm(0); signal(SIGALRM, SIG_IGN); LM_DBG("terminating due to SIGCHLD\n"); exit(0); break; case SIGHUP: /* ignoring it*/ LM_DBG("SIGHUP received, ignoring it\n"); break; default: LM_CRIT("unhandled signal %d\n", sig_flag); } sig_flag=0; }