X-Git-Url: https://git.distorted.org.uk/~mdw/disorder/blobdiff_plain/e04f4cb529108fc02c44eda228f96434c1086956..6961095b797229842e1465ff3670625d11e95167:/server/state.c diff --git a/server/state.c b/server/state.c index a881e9b..b125417 100644 --- a/server/state.c +++ b/server/state.c @@ -46,11 +46,27 @@ const struct uaudio *api; /** @brief Quit DisOrder */ void quit(ev_source *ev) { - info("shutting down..."); + disorder_info("shutting down..."); quitting(ev); trackdb_close(); - trackdb_deinit(); - info("exiting"); + trackdb_deinit(ev); + /* Shutdown subprocesses. + * + * Subprocesses that use ev_child: + * - the speaker + * - the current rescan + * - any decoders + * - ...and players + * - the track picker + * - mail sender + * - the deadlock manager + * + * Subprocesses that don't: + * - any normalizers + * These are not shut down currently. + */ + ev_child_killall(ev); + disorder_info("exiting"); exit(0); } @@ -62,7 +78,7 @@ static struct sockaddr *copy_sockaddr(const struct addrinfo *addr) { } /** @brief Create and destroy sockets to set current configuration */ -static void reset_socket(ev_source *ev) { +void reset_sockets(ev_source *ev) { const char *new_unix; struct addrinfo *res, *r; struct listener *l, **ll; @@ -76,22 +92,22 @@ static void reset_socket(ev_source *ev) { /* stop the old one and remove it from the filesystem */ server_stop(ev, current_unix_fd); if(unlink(current_unix) < 0) - fatal(errno, "unlink %s", current_unix); + disorder_fatal(errno, "unlink %s", current_unix); } /* start the new one */ if(strlen(new_unix) >= sizeof sun.sun_path) - fatal(0, "socket path %s is too long", new_unix); + disorder_fatal(0, "socket path %s is too long", new_unix); memset(&sun, 0, sizeof sun); sun.sun_family = AF_UNIX; strcpy(sun.sun_path, new_unix); if(unlink(new_unix) < 0 && errno != ENOENT) - fatal(errno, "unlink %s", new_unix); + disorder_fatal(errno, "unlink %s", new_unix); if((current_unix_fd = server_start(ev, PF_UNIX, sizeof sun, (const struct sockaddr *)&sun, new_unix)) >= 0) { current_unix = new_unix; if(chmod(new_unix, 0777) < 0) - fatal(errno, "error calling chmod %s", new_unix); + disorder_fatal(errno, "error calling chmod %s", new_unix); } else current_unix = 0; } @@ -144,39 +160,34 @@ static void reset_socket(ev_source *ev) { } /** @brief Reconfigure the server - * @param reload 0 at startup, 1 for a reload + * @param ev Event loop + * @param flags Flags + * @return As config_read(); 0 on success, -1 if could not (re-)read config */ -int reconfigure(ev_source *ev, int reload) { +int reconfigure(ev_source *ev, unsigned flags) { int need_another_rescan = 0; int ret = 0; - D(("reconfigure(%d)", reload)); + D(("reconfigure(%x)", flags)); /* Deconfigure the old audio API if there is one */ if(api) { if(api->close_mixer) api->close_mixer(); api = NULL; } - if(reload) { + if(flags & RECONFIGURE_RELOADING) { /* If there's a rescan in progress, cancel it but remember to start a fresh - * one after the reload */ + * one after the reload. */ need_another_rescan = trackdb_rescan_cancel(); - /* Close the track database */ - trackdb_close(); /* (Re-)read the configuration */ - if(config_read(1/*server*/)) + if(config_read(1/*server*/, config)) ret = -1; else { /* Tell the speaker it needs to reload its config too. */ speaker_reload(); - info("%s: installed new configuration", configfile); + disorder_info("%s: installed new configuration", configfile); } - /* Re-open track database. We don't attempt to support database version - * upgrade at this point - the software hasn't changed, after all. */ - trackdb_open(TRACKDB_NO_UPGRADE); - } else - /* We only allow for upgrade at startup */ - trackdb_open(TRACKDB_CAN_UPGRADE); + } /* New audio API */ api = uaudio_find(config->api); if(api->configure) @@ -186,35 +197,10 @@ int reconfigure(ev_source *ev, int reload) { /* If we interrupted a rescan of all the tracks, start a new one */ if(need_another_rescan) trackdb_rescan(ev, 1/*check*/, 0, 0); - /* Arrange timeouts for schedule actions */ - schedule_init(ev); - /* TODO what about leftover callbacks from before the reload? */ - if(!ret) { - /* Read the queue back in */ - queue_read(); - recent_read(); - /* Reset sockets */ - reset_socket(ev); + if(!ret && !(flags & RECONFIGURE_FIRST)) { + /* Open/close sockets */ + reset_sockets(ev); } - /* TODO we need a careful think about what you can and cannot change with a - * reload. - * - * For instance saving and restoring the queue limits what we can usefuly - * keep in the queue data structure. As a general rule, long-term state - * ought to be off-limits. So 'home directory' will have to stay where it - * is. (This actually means the AF_UNIX socket will never be re-opened.) - * - * Players certainly ought to be reconfigurable but this raises the ugly - * question of what to do about already-started background decoders. - * - * The audio API is easy to do for the server but a pain for the speaker. - * - * These two points suggest a general approach: if things that affect the - * speaker change, we could just restart it and any extant background - * decoders, at the next track change. This would generate a bit of a gap - * but presumably reconfiguration is a rare event so this might be - * acceptable. - */ return ret; }