/** The mutex protecting the shared memory area containing the mmd struct. */
int mmd_mutex;
+/* Serializes log output. */
+static int log_mutex;
+
static struct sched sched;
static struct signal_task *signal_task;
return get_task_list(&sched);
}
-/*
- * setup shared memory area and get mutex for locking
- */
+static void pre_log_hook(void)
+{
+ mutex_lock(log_mutex);
+}
+
+static void post_log_hook(void)
+{
+ mutex_unlock(log_mutex);
+}
+
+/* Setup shared memory area and init mutexes */
static void init_ipc_or_die(void)
{
void *shm;
if (ret < 0)
goto err_out;
mmd_mutex = ret;
+ ret = mutex_new();
+ if (ret < 0)
+ goto destroy_mmd_mutex;
+ log_mutex = ret;
mmd->num_played = 0;
mmd->num_commands = 0;
mmd->vss_status_flags = VSS_NEXT;
mmd->new_vss_status_flags = VSS_NEXT;
return;
+destroy_mmd_mutex:
+ mutex_destroy(mmd_mutex);
err_out:
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
exit(EXIT_FAILURE);
daemon_set_flag(DF_LOG_TIMING);
daemon_set_priority(OPT_UINT32_VAL(PRIORITY));
if (user_list_file)
- init_user_list(user_list_file);
+ user_list_init(user_list_file);
ret = 1;
free_cf:
free(cf);
PARA_EMERG_LOG("terminating on signal %d\n", signum);
kill(0, SIGTERM);
/*
- * We must wait for afs because afs catches SIGINT/SIGTERM.
- * Before reacting to the signal, afs might want to use the
+ * We must wait for all of our children to die. For the afs
+ * process or a command handler 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)afs_pid);
- waitpid(afs_pid, NULL, 0);
+ PARA_INFO_LOG("waiting for child processes to die\n");
+ mutex_unlock(mmd_mutex);
+ while (wait(NULL) != -1 || errno != ECHILD)
+ ; /* still at least one child alive */
+ mutex_lock(mmd_mutex);
cleanup:
free(mmd->afd.afhi.chunk_table);
- close_listed_fds();
- mutex_destroy(mmd_mutex);
- shm_detach(mmd);
- exit(EXIT_FAILURE);
+ task_notify_all(s, E_DEADLY_SIGNAL);
+ return -E_DEADLY_SIGNAL;
}
return 0;
}
server_pid = getpid();
init_random_seed_or_die();
daemon_log_welcome("server");
- init_ipc_or_die(); /* init mmd struct and mmd->lock */
+ init_ipc_or_die(); /* init mmd struct, mmd and log mutex */
daemon_set_start_time();
+ daemon_set_hooks(pre_log_hook, post_log_hook);
PARA_NOTICE_LOG("initializing audio format handlers\n");
afh_init();
server_init(argc, argv, sct);
mutex_lock(mmd_mutex);
ret = schedule(&sched);
+ /*
+ * We hold the mmd lock: it was re-acquired in server_select()
+ * after the select call.
+ */
+ mutex_unlock(mmd_mutex);
sched_shutdown(&sched);
signal_shutdown(signal_task);
if (!process_is_command_handler()) { /* parent (server) */
+ mutex_destroy(mmd_mutex);
+ daemon_set_hooks(NULL, NULL); /* only one process remaining */
+ mutex_destroy(log_mutex);
+ shm_detach(mmd);
+ deplete_close_on_fork_list();
if (ret < 0)
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
} else {
- /*
- * We hold the mmd lock: it was re-acquired in server_select()
- * after the select call.
- */
- mutex_unlock(mmd_mutex);
alarm(ALARM_TIMEOUT);
close_listed_fds();
ret = handle_connect(sct->child_fd);
}
vss_shutdown();
+ shm_detach(mmd);
+ user_list_deplete();
lls_free_parse_result(server_lpr, CMD_PTR);
if (server_lpr != cmdline_lpr)
lls_free_parse_result(cmdline_lpr, CMD_PTR);