X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=server.c;h=a4115eb65734391128481f6fa421d548aba78e20;hp=9c06991378512172e95b70165118ae1ea873bdb1;hb=ad81d625737e1c096c154aedd8a1d161d3ee592e;hpb=26d662890f5e1c29c0b09d1cac94b8b4acb065ed diff --git a/server.c b/server.c index 9c069913..a4115eb6 100644 --- a/server.c +++ b/server.c @@ -300,6 +300,9 @@ static void signal_post_select(struct sched *s, struct task *t) PARA_EMERG_LOG("terminating on signal %d\n", st->signum); genocide: kill(0, SIGTERM); + free(mmd->afd.afhi.chunk_table); + free(mmd->afd.afhi.info_string); + close_listed_fds(); mutex_destroy(mmd_mutex); shm_detach(mmd); exit(EXIT_FAILURE); @@ -349,6 +352,8 @@ static void command_post_select(struct sched *s, struct task *t) int new_fd, ret, i; char *peer_name; pid_t child_pid; + uint32_t *chunk_table; + char *info_string; if (!FD_ISSET(sct->listen_fd, &s->rfds)) return; @@ -361,6 +366,16 @@ static void command_post_select(struct sched *s, struct task *t) mmd->num_connects++; mmd->active_connections++; random(); + /* The chunk table and the info_string are pointers located in the + * mmd struct that point to dynamically allocated memory that must be + * freed by the parent and the child. However, as the mmd struct is in + * a shared memory area, there's no guarantee that after the fork these + * pointers are still valid in child context. As these two pointers are + * not used in the child anyway, we save them to local variables and + * free the memory via that copy in the child. + */ + info_string = mmd->afd.afhi.info_string; + chunk_table = mmd->afd.afhi.chunk_table; child_pid = fork(); if (child_pid < 0) { ret = -ERRNO_TO_PARA_ERROR(errno); @@ -371,6 +386,9 @@ static void command_post_select(struct sched *s, struct task *t) /* parent keeps accepting connections */ return; } + /* mmd might already have changed at this point */ + free(info_string); + free(chunk_table); alarm(ALARM_TIMEOUT); close_listed_fds(); para_signal_shutdown(); @@ -467,6 +485,12 @@ static int init_afs(void) return afs_server_socket[0]; } +__noreturn static void tmp_sigchld_handler(__a_unused int s) +{ + PARA_EMERG_LOG("caught early SIGCHLD\n"); + exit(EXIT_FAILURE); +} + static void server_init(int argc, char **argv) { struct server_cmdline_parser_params params = { @@ -509,6 +533,15 @@ static void server_init(int argc, char **argv) PARA_EMERG_LOG("failed to ignore SIGUSR1\n"); exit(EXIT_FAILURE); } + /* + * 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_NOTICE_LOG("initializing the audio file selector\n"); afs_socket = init_afs(); init_signal_task();