X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=server.c;h=2e5f5f748887f91e257f8065c134d53253f1b7af;hp=a4115eb65734391128481f6fa421d548aba78e20;hb=33a282ec9378ca6b2d0707c6e9642a3e6b625cb4;hpb=ad81d625737e1c096c154aedd8a1d161d3ee592e diff --git a/server.c b/server.c index a4115eb6..2e5f5f74 100644 --- a/server.c +++ b/server.c @@ -59,7 +59,7 @@ * - Ring buffer: \ref ringbuffer.c, \ref ringbuffer.h, * - Hashing: \ref hash.h, \ref sha1.h, \ref sha1.c, * - Crypto: \ref crypt.c. - * + * - Forward error correction: \ref fec.c */ #include @@ -291,15 +291,32 @@ static void signal_post_select(struct sched *s, struct task *t) if (pid != mmd->afs_pid) continue; PARA_EMERG_LOG("fatal: afs died\n"); - goto genocide; + kill(0, SIGTERM); + goto cleanup; } break; /* die on sigint/sigterm. Kill all children too. */ case SIGINT: case SIGTERM: PARA_EMERG_LOG("terminating on signal %d\n", st->signum); -genocide: kill(0, SIGTERM); + /* + * We must wait for afs because afs catches SIGINT/SIGTERM. + * Before reacting to the signal, afs might want to use the + * shared memory area and the mmd mutex. If we destroy this + * mutex too early and afs tries to lock the shared memory + * area, the call to mutex_lock() will fail and terminate the + * afs process. This leads to dirty osl tables. + * + * There's no such problem with the other children of the + * server process (the command handlers) as these reset their + * SIGINT/SIGTERM handlers to the default action, i.e. these + * processes get killed immediately by the above kill(). + */ + PARA_INFO_LOG("waiting for afs (pid %d) to die\n", + (int)mmd->afs_pid); + waitpid(mmd->afs_pid, NULL, 0); +cleanup: free(mmd->afd.afhi.chunk_table); free(mmd->afd.afhi.info_string); close_listed_fds(); @@ -318,25 +335,15 @@ static void init_signal_task(void) st->task.post_select = signal_post_select; sprintf(st->task.status, "signal task"); + PARA_NOTICE_LOG("setting up signal handling\n"); st->fd = para_signal_init(); /* always successful */ - - PARA_NOTICE_LOG("setting up signal handlers\n"); - if (para_install_sighandler(SIGINT) < 0) - goto err; - if (para_install_sighandler(SIGTERM) < 0) - goto err; - if (para_install_sighandler(SIGHUP) < 0) - goto err; - if (para_install_sighandler(SIGCHLD) < 0) - goto err; - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) - goto err; + para_install_sighandler(SIGINT); + para_install_sighandler(SIGTERM); + para_install_sighandler(SIGHUP); + para_install_sighandler(SIGCHLD); + para_sigaction(SIGPIPE, SIG_IGN); add_close_on_fork_list(st->fd); register_task(&st->task); - return; -err: - PARA_EMERG_LOG("could not install signal handlers\n"); - exit(EXIT_FAILURE); } static void command_pre_select(struct sched *s, struct task *t) @@ -529,19 +536,13 @@ static void server_init(int argc, char **argv) * before the child gets a chance to ignore this signal -- only the * good die young. */ - if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) { - PARA_EMERG_LOG("failed to ignore SIGUSR1\n"); - exit(EXIT_FAILURE); - } + para_sigaction(SIGUSR1, SIG_IGN); /* * We have to install a SIGCHLD handler before the afs process is being * forked off. Otherwise, para_server does not notice if afs dies before * the SIGCHLD handler has been installed by init_signal_task() below. */ - if (signal(SIGCHLD, tmp_sigchld_handler) == SIG_ERR) { - PARA_EMERG_LOG("failed to install temporary SIGCHLD handler\n"); - exit(EXIT_FAILURE); - } + para_sigaction(SIGCHLD, tmp_sigchld_handler); PARA_NOTICE_LOG("initializing the audio file selector\n"); afs_socket = init_afs(); init_signal_task();