X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=server.c;h=e0d50f4f8689e1de283ef80f8341504bcf386d33;hp=eee0a4128e9218233dad9e316d6cc9c1658a6cbb;hb=HEAD;hpb=7e611b37e41f0ec7ec6d3173b7e88ed5b9b3a276 diff --git a/server.c b/server.c index eee0a412..ea9cc9c0 100644 --- a/server.c +++ b/server.c @@ -2,31 +2,6 @@ /** \file server.c Paraslash's main server. */ -/** - * \mainpage Main data structures and selected APIs: - * - * - Senders: \ref sender, - * - Audio file selector: \ref afs_info, \ref afs_table, - * - Audio format handler: \ref audio_format_handler, \ref afh_info - * - Receivers/filters/writers: \ref receiver, \ref receiver_node, - * \ref filter, \ref filter_node, \ref writer_node, \ref writer. - * - Scheduling: \ref sched.h, - * - Buffer trees: \ref buffer_tree.h, - * - Sideband API: \ref sideband.h, - * - Crypto: \ref crypt.h, \ref crypt_backend.h, - * - Error subsystem: \ref error.h, - * - Inter process communication: \ref ipc.h, - * - Forward error correction: \ref fec.h, - * - Daemons: \ref daemon.h, - * - Mixer API: \ref mix.h, - * - Interactive sessions: \ref interactive.h, - * - File descriptors: \ref fd.h, - * - Signals: \ref signal.h, - * - Networking: \ref net.h, - * - Time: \ref time.c, - * - Doubly linked lists: \ref list.h. - */ - #include #include #include @@ -49,8 +24,8 @@ #include "net.h" #include "server.h" #include "list.h" -#include "send.h" #include "sched.h" +#include "send.h" #include "vss.h" #include "config.h" #include "close_on_fork.h" @@ -110,7 +85,7 @@ static struct signal_task *signal_task; /** The process id of the audio file selector process. */ pid_t afs_pid = 0; -/* The the main server process (parent of afs and the command handlers). */ +/* The main server process (parent of afs and the command handlers). */ static pid_t server_pid; /** @@ -197,6 +172,7 @@ static void init_ipc_or_die(void) mmd->active_connections = 0; mmd->vss_status_flags = VSS_NEXT; mmd->new_vss_status_flags = VSS_NEXT; + mmd->loglevel = OPT_UINT32_VAL(LOGLEVEL); return; destroy_mmd_mutex: mutex_destroy(mmd_mutex); @@ -205,6 +181,9 @@ err_out: exit(EXIT_FAILURE); } +/** Get a reference to the supercommand of para_server. */ +#define CMD_PTR (lls_cmd(0, server_suite)) + /** * (Re-)read the server configuration files. * @@ -230,7 +209,7 @@ void parse_config_or_die(bool reload) para_strerror(-ret)); exit(EXIT_FAILURE); } - daemon_set_loglevel(ENUM_STRING_VAL(LOGLEVEL)); + daemon_set_loglevel(OPT_UINT32_VAL(LOGLEVEL)); if (OPT_GIVEN(LOGFILE)) { daemon_set_logfile(OPT_STRING_VAL(LOGFILE)); daemon_open_log_or_die(); @@ -275,14 +254,14 @@ static void handle_sighup(void) kill(afs_pid, SIGHUP); } -static int signal_post_select(struct sched *s, __a_unused void *context) +static int signal_post_monitor(struct sched *s, __a_unused void *context) { int ret, signum; ret = task_get_notification(signal_task->task); if (ret < 0) return ret; - signum = para_next_signal(&s->rfds); + signum = para_next_signal(); switch (signum) { case 0: return 0; @@ -298,14 +277,14 @@ static int signal_post_select(struct sched *s, __a_unused void *context) if (pid != afs_pid) continue; PARA_EMERG_LOG("fatal: afs died\n"); - kill(0, SIGTERM); - goto cleanup; + goto genocide; } break; /* die on sigint/sigterm. Kill all children too. */ case SIGINT: case SIGTERM: PARA_EMERG_LOG("terminating on signal %d\n", signum); +genocide: kill(0, SIGTERM); /* * We must wait for all of our children to die. For the afs @@ -320,7 +299,6 @@ static int signal_post_select(struct sched *s, __a_unused void *context) while (wait(NULL) != -1 || errno != ECHILD) ; /* still at least one child alive */ mutex_lock(mmd_mutex); -cleanup: free(mmd->afd.afhi.chunk_table); task_notify_all(s, E_DEADLY_SIGNAL); return -E_DEADLY_SIGNAL; @@ -339,20 +317,20 @@ static void init_signal_task(void) add_close_on_fork_list(signal_task->fd); signal_task->task = task_register(&(struct task_info) { .name = "signal", - .pre_select = signal_pre_select, - .post_select = signal_post_select, + .pre_monitor = signal_pre_monitor, + .post_monitor = signal_post_monitor, .context = signal_task, }, &sched); } -static void command_pre_select(struct sched *s, void *context) +static void command_pre_monitor(struct sched *s, void *context) { unsigned n; struct server_command_task *sct = context; for (n = 0; n < sct->num_listen_fds; n++) - para_fd_set(sct->listen_fds[n], &s->rfds, &s->max_fileno); + sched_monitor_readfd(sct->listen_fds[n], s); } static int command_task_accept(unsigned listen_idx, struct sched *s, @@ -363,7 +341,7 @@ static int command_task_accept(unsigned listen_idx, struct sched *s, pid_t child_pid; uint32_t *chunk_table; - ret = para_accept(sct->listen_fds[listen_idx], &s->rfds, NULL, 0, &new_fd); + ret = para_accept(sct->listen_fds[listen_idx], NULL, 0, &new_fd); if (ret <= 0) goto out; mmd->num_connects++; @@ -409,13 +387,13 @@ static int command_task_accept(unsigned listen_idx, struct sched *s, /* * After we return, the scheduler calls server_select() with a minimal * timeout value, because the remaining tasks have a notification - * pending. Next it calls the ->post_select method of these tasks, + * pending. Next it calls the ->post_monitor method of these tasks, * which will return negative in view of the notification. This causes * schedule() to return as there are no more runnable tasks. * * Note that semaphores are not inherited across a fork(), so we don't - * hold the lock at this point. Since server_select() drops the lock - * prior to calling para_select(), we need to acquire it here. + * hold the lock at this point. Since server_poll() drops the lock + * prior to calling poll(), we need to acquire it here. */ mutex_lock(mmd_mutex); return -E_CHILD_CONTEXT; @@ -425,7 +403,7 @@ out: return 0; } -static int command_post_select(struct sched *s, void *context) +static int command_post_monitor(struct sched *s, void *context) { struct server_command_task *sct = context; unsigned n; @@ -433,15 +411,16 @@ static int command_post_select(struct sched *s, void *context) ret = task_get_notification(sct->task); if (ret < 0) - return ret; + goto fail; for (n = 0; n < sct->num_listen_fds; n++) { ret = command_task_accept(n, s, sct); - if (ret < 0) { - free(sct->listen_fds); - return ret; - } + if (ret < 0) + goto fail; } return 0; +fail: + free(sct->listen_fds); + return ret; } static void init_server_command_task(struct server_command_task *sct, @@ -457,14 +436,14 @@ static void init_server_command_task(struct server_command_task *sct, sct->argv = argv; if (!OPT_GIVEN(LISTEN_ADDRESS)) { sct->num_listen_fds = 1; - sct->listen_fds = para_malloc(sizeof(int)); + sct->listen_fds = alloc(sizeof(int)); ret = para_listen_simple(IPPROTO_TCP, port); if (ret < 0) goto err; sct->listen_fds[0] = ret; } else { sct->num_listen_fds = OPT_GIVEN(LISTEN_ADDRESS); - sct->listen_fds = para_malloc(sct->num_listen_fds * sizeof(int)); + sct->listen_fds = alloc(sct->num_listen_fds * sizeof(int)); for (n = 0; n < OPT_GIVEN(LISTEN_ADDRESS); n++) { const char *arg; arg = lls_string_val(n, OPT_RESULT(LISTEN_ADDRESS)); @@ -484,10 +463,17 @@ static void init_server_command_task(struct server_command_task *sct, sct->task = task_register(&(struct task_info) { .name = "server command", - .pre_select = command_pre_select, - .post_select = command_post_select, + .pre_monitor = command_pre_monitor, + .post_monitor = command_post_monitor, .context = sct, }, &sched); + /* + * Detect whether the abstract Unix domain socket space is supported, + * but do not create the socket. We check this once in server context + * so that the command handlers inherit this bit of information and + * don't need to check again. + */ + create_local_socket(NULL); return; err: PARA_EMERG_LOG("%s\n", para_strerror(-ret)); @@ -561,7 +547,7 @@ static void server_init(int argc, char **argv, struct server_command_task *sct) if (ret < 0) goto fail; server_lpr = cmdline_lpr; - daemon_set_loglevel(ENUM_STRING_VAL(LOGLEVEL)); + daemon_set_loglevel(OPT_UINT32_VAL(LOGLEVEL)); daemon_drop_privileges_or_die(OPT_STRING_VAL(USER), OPT_STRING_VAL(GROUP)); version_handle_flag("server", OPT_GIVEN(VERSION)); @@ -576,9 +562,6 @@ static void server_init(int argc, char **argv, struct server_command_task *sct) 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(); - /* * Although afs uses its own signal handling we must ignore SIGUSR1 * _before_ the afs child process gets born by init_afs() below. It's @@ -638,14 +621,14 @@ out: killpg(0, SIGUSR1); } -static int server_select(int max_fileno, fd_set *readfds, fd_set *writefds, - struct timeval *timeout_tv) +static int server_poll(struct pollfd *fds, nfds_t nfds, int timeout) { int ret; + daemon_set_loglevel(mmd->loglevel); status_refresh(); mutex_unlock(mmd_mutex); - ret = para_select(max_fileno + 1, readfds, writefds, timeout_tv); + ret = xpoll(fds, nfds, timeout); mutex_lock(mmd_mutex); return ret; } @@ -679,15 +662,15 @@ int main(int argc, char *argv[]) struct server_command_task server_command_task_struct, *sct = &server_command_task_struct; - sched.default_timeout.tv_sec = 1; - sched.select_function = server_select; + sched.default_timeout = 1000; + sched.poll_function = server_poll; 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. + * We hold the mmd lock: it was re-acquired in server_poll() + * after the poll(2) call. */ mutex_unlock(mmd_mutex); sched_shutdown(&sched); @@ -700,12 +683,13 @@ int main(int argc, char *argv[]) deplete_close_on_fork_list(); if (ret < 0) PARA_EMERG_LOG("%s\n", para_strerror(-ret)); + vss_shutdown(); } else { + vss_shutdown(); alarm(ALARM_TIMEOUT); close_listed_fds(); ret = handle_connect(sct->child_fd); } - vss_shutdown(); shm_detach(mmd); user_list_deplete(); free_lpr();