/** The file containing user information (public key, permissions). */
static char *user_list_file = NULL;
-static int mmd_shm_id;
/** The task responsible for server command handling. */
static void init_ipc_or_die(void)
{
void *shm;
- int ret = shm_new(sizeof(struct misc_meta_data));
+ int shmid, ret = shm_new(sizeof(struct misc_meta_data));
if (ret < 0)
goto err_out;
-
- ret = shm_attach(ret, ATTACH_RW, &shm);
+ shmid = ret;
+ ret = shm_attach(shmid, ATTACH_RW, &shm);
+ shm_destroy(shmid);
if (ret < 0)
goto err_out;
mmd = shm;
- mmd_shm_id = ret;
ret = mutex_new();
if (ret < 0)
.initialize = 0,
.check_required = 1,
.check_ambiguity = 0,
- .print_errors = 1
+ .print_errors = !conf.daemon_given
};
server_cmdline_parser_config_file(cf, &conf, ¶ms);
conf.daemon_given = tmp;
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);
- shm_destroy(mmd_shm_id);
-
exit(EXIT_FAILURE);
}
}
goto err;
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
goto err;
- if (signal(SIGUSR1, SIG_IGN) == SIG_ERR)
- goto err;
add_close_on_fork_list(st->fd);
register_task(&st->task);
return;
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 = {
daemonize();
PARA_NOTICE_LOG("initializing audio format handlers\n");
afh_init();
+
+ /*
+ * Although afs uses its own signal handling we must ignore SIGUSR1
+ * _before_ the afs child process gets born by init_afs() below. It's
+ * racy to do this in the child because the parent might send SIGUSR1
+ * 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);
+ }
+ /*
+ * 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();