From 756fac8d0433d02819d3910238ebf1b7a33a3046 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Aug 2008 19:39:12 +0200 Subject: add new switch --disallow-exit --- src/daemon/cmdline.c | 13 ++++++++- src/daemon/daemon-conf.c | 60 ++++++++++++++++++++++------------------- src/daemon/daemon-conf.h | 3 ++- src/daemon/main.c | 1 + src/modules/module-cli.c | 2 +- src/pulsecore/cli-command.c | 4 ++- src/pulsecore/client.c | 4 +-- src/pulsecore/core.c | 37 ++++++++++++++++--------- src/pulsecore/core.h | 7 +++-- src/pulsecore/protocol-native.c | 4 ++- src/utils/pactl.c | 4 +-- 11 files changed, 87 insertions(+), 52 deletions(-) diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index 3121da60..fbd6dc32 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -50,6 +50,7 @@ enum { ARG_HIGH_PRIORITY, ARG_REALTIME, ARG_DISALLOW_MODULE_LOADING, + ARG_DISALLOW_EXIT, ARG_EXIT_IDLE_TIME, ARG_MODULE_IDLE_TIME, ARG_SCACHE_IDLE_TIME, @@ -82,6 +83,7 @@ static const struct option long_options[] = { {"high-priority", 2, 0, ARG_HIGH_PRIORITY}, {"realtime", 2, 0, ARG_REALTIME}, {"disallow-module-loading", 2, 0, ARG_DISALLOW_MODULE_LOADING}, + {"disallow-exit", 2, 0, ARG_DISALLOW_EXIT}, {"exit-idle-time", 2, 0, ARG_EXIT_IDLE_TIME}, {"module-idle-time", 2, 0, ARG_MODULE_IDLE_TIME}, {"scache-idle-time", 2, 0, ARG_SCACHE_IDLE_TIME}, @@ -134,7 +136,9 @@ void pa_cmdline_help(const char *argv0) { " --realtime[=BOOL] Try to enable realtime scheduling\n" " (only available as root, when SUID or\n" " with elevated RLIMIT_RTPRIO)\n" - " --disallow-module-loading[=BOOL] Disallow module loading after startup\n" + " --disallow-module-loading[=BOOL] Disallow module user requested module\n" + " loading/unloading after startup\n" + " --disallow-exit[=BOOL] Disallow user requested exit\n" " --exit-idle-time=SECS Terminate the daemon when idle and this\n" " time passed\n" " --module-idle-time=SECS Unload autoloaded modules when idle and\n" @@ -286,6 +290,13 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d } break; + case ARG_DISALLOW_EXIT: + if ((conf->disallow_exit = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { + pa_log(_("--disallow-exit boolean argument")); + goto fail; + } + break; + case ARG_USE_PID_FILE: if ((conf->use_pid_file = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log(_("--use-pid-file expects boolean argument")); diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index a6b27c55..05c86c87 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -63,6 +63,7 @@ static const pa_daemon_conf default_conf = { .realtime_scheduling = FALSE, .realtime_priority = 5, /* Half of JACK's default rtprio */ .disallow_module_loading = FALSE, + .disallow_exit = FALSE, .exit_idle_time = 20, .module_idle_time = 20, .scache_idle_time = 20, @@ -403,6 +404,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "high-priority", pa_config_parse_bool, NULL }, { "realtime-scheduling", pa_config_parse_bool, NULL }, { "disallow-module-loading", pa_config_parse_bool, NULL }, + { "disallow-exit", pa_config_parse_bool, NULL }, { "use-pid-file", pa_config_parse_bool, NULL }, { "system-instance", pa_config_parse_bool, NULL }, { "no-cpu-limit", pa_config_parse_bool, NULL }, @@ -466,17 +468,17 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[2].data = &c->high_priority; table[3].data = &c->realtime_scheduling; table[4].data = &c->disallow_module_loading; - table[5].data = &c->use_pid_file; - table[6].data = &c->system_instance; - table[7].data = &c->no_cpu_limit; - table[8].data = &c->disable_shm; - table[9].data = &c->exit_idle_time; - table[10].data = &c->module_idle_time; - table[11].data = &c->scache_idle_time; - table[12].data = c; - table[13].data = &c->dl_search_path; - table[14].data = &c->default_script_file; - table[15].data = c; + table[5].data = &c->disallow_exit; + table[6].data = &c->use_pid_file; + table[7].data = &c->system_instance; + table[8].data = &c->no_cpu_limit; + table[9].data = &c->disable_shm; + table[10].data = &c->exit_idle_time; + table[11].data = &c->module_idle_time; + table[12].data = &c->scache_idle_time; + table[13].data = c; + table[14].data = &c->dl_search_path; + table[15].data = &c->default_script_file; table[16].data = c; table[17].data = c; table[18].data = c; @@ -486,67 +488,68 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[22].data = c; table[23].data = c; table[24].data = c; - table[25].data = &c->disable_remixing; - table[26].data = &c->load_default_script_file; + table[25].data = c; + table[26].data = &c->disable_remixing; + table[27].data = &c->load_default_script_file; #ifdef HAVE_SYS_RESOURCE_H - table[27].data = &c->rlimit_fsize; - table[28].data = &c->rlimit_data; - table[29].data = &c->rlimit_stack; - table[30].data = &c->rlimit_as; - table[31].data = &c->rlimit_core; - table[32].data = &c->rlimit_nofile; - table[33].data = &c->rlimit_as; + table[28].data = &c->rlimit_fsize; + table[29].data = &c->rlimit_data; + table[30].data = &c->rlimit_stack; + table[31].data = &c->rlimit_as; + table[32].data = &c->rlimit_core; + table[33].data = &c->rlimit_nofile; + table[34].data = &c->rlimit_as; #ifdef RLIMIT_NPROC - table[34].data = &c->rlimit_nproc; + table[35].data = &c->rlimit_nproc; #endif #ifdef RLIMIT_MEMLOCK #ifndef RLIMIT_NPROC #error "Houston, we have a numbering problem!" #endif - table[35].data = &c->rlimit_memlock; + table[36].data = &c->rlimit_memlock; #endif #ifdef RLIMIT_LOCKS #ifndef RLIMIT_MEMLOCK #error "Houston, we have a numbering problem!" #endif - table[36].data = &c->rlimit_locks; + table[37].data = &c->rlimit_locks; #endif #ifdef RLIMIT_SIGPENDING #ifndef RLIMIT_LOCKS #error "Houston, we have a numbering problem!" #endif - table[37].data = &c->rlimit_sigpending; + table[38].data = &c->rlimit_sigpending; #endif #ifdef RLIMIT_MSGQUEUE #ifndef RLIMIT_SIGPENDING #error "Houston, we have a numbering problem!" #endif - table[38].data = &c->rlimit_msgqueue; + table[39].data = &c->rlimit_msgqueue; #endif #ifdef RLIMIT_NICE #ifndef RLIMIT_MSGQUEUE #error "Houston, we have a numbering problem!" #endif - table[39].data = &c->rlimit_nice; + table[40].data = &c->rlimit_nice; #endif #ifdef RLIMIT_RTPRIO #ifndef RLIMIT_NICE #error "Houston, we have a numbering problem!" #endif - table[40].data = &c->rlimit_rtprio; + table[41].data = &c->rlimit_rtprio; #endif #ifdef RLIMIT_RTTIME #ifndef RLIMIT_RTTIME #error "Houston, we have a numbering problem!" #endif - table[41].data = &c->rlimit_rttime; + table[42].data = &c->rlimit_rttime; #endif #endif @@ -643,6 +646,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling)); pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority); pa_strbuf_printf(s, "disallow-module-loading = %s\n", pa_yes_no(c->disallow_module_loading)); + pa_strbuf_printf(s, "disallow-exit = %s\n", pa_yes_no(c->disallow_exit)); pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file)); pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance)); pa_strbuf_printf(s, "no-cpu-limit = %s\n", pa_yes_no(c->no_cpu_limit)); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index be2fe1ab..c42984f9 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -66,7 +66,8 @@ typedef struct pa_daemon_conf { no_cpu_limit, disable_shm, disable_remixing, - load_default_script_file; + load_default_script_file, + disallow_exit; int exit_idle_time, module_idle_time, scache_idle_time, diff --git a/src/daemon/main.c b/src/daemon/main.c index 2579c182..048af1e6 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -813,6 +813,7 @@ int main(int argc, char *argv[]) { c->realtime_scheduling = !!conf->realtime_scheduling; c->disable_remixing = !!conf->disable_remixing; c->running_as_daemon = !!conf->daemonize; + c->disallow_exit = conf->disallow_exit; pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_signal_new(SIGINT, signal_callback, c); diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c index 7a58877a..439aa8b0 100644 --- a/src/modules/module-cli.c +++ b/src/modules/module-cli.c @@ -62,7 +62,7 @@ static void eof_and_exit_cb(pa_cli*c, void *userdata) { pa_assert(c); pa_assert(m); - m->core->mainloop->quit(m->core->mainloop, 0); + pa_core_exit(m->core, FALSE, 0); } int pa__init(pa_module*m) { diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 8e8f5f28..a80933fa 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -188,7 +188,9 @@ static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b pa_assert(buf); pa_assert(fail); - c->mainloop->quit(c->mainloop, 0); + if (pa_core_exit(c, FALSE, 0) < 0) + pa_strbuf_puts(buf, "Not allowed to terminate daemon.\n"); + return 0; } diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c index 0ffd2330..ab6e5df4 100644 --- a/src/pulsecore/client.c +++ b/src/pulsecore/client.c @@ -58,7 +58,7 @@ pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) { pa_log_info("Created %u \"%s\"", c->index, pa_strnull(name)); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); - pa_core_check_quit(core); + pa_core_check_idle(core); return c; } @@ -78,7 +78,7 @@ void pa_client_free(pa_client *c) { pa_xfree(c->driver); pa_xfree(c); - pa_core_check_quit(core); + pa_core_check_idle(core); } void pa_client_kill(pa_client *c) { diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 5e40ea88..5c594b02 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -125,7 +125,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { c->mempool = pool; pa_silence_cache_init(&c->silence_cache); - c->quit_event = NULL; + c->exit_event = NULL; c->exit_idle_time = -1; c->module_idle_time = 20; @@ -134,6 +134,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3; c->disallow_module_loading = FALSE; + c->disallow_exit = FALSE; c->realtime_scheduling = FALSE; c->realtime_priority = 5; c->disable_remixing = FALSE; @@ -149,7 +150,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { pa_check_signal_is_blocked(SIGPIPE); #endif - pa_core_check_quit(c); + pa_core_check_idle(c); return c; } @@ -182,8 +183,8 @@ static void core_free(pa_object *o) { pa_autoload_free(c); pa_subscription_free_all(c); - if (c->quit_event) - c->mainloop->time_free(c->quit_event); + if (c->exit_event) + c->mainloop->time_free(c->exit_event); pa_xfree(c->default_source_name); pa_xfree(c->default_sink_name); @@ -199,17 +200,17 @@ static void core_free(pa_object *o) { pa_xfree(c); } -static void quit_callback(pa_mainloop_api*m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { +static void exit_callback(pa_mainloop_api*m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { pa_core *c = userdata; - pa_assert(c->quit_event == e); + pa_assert(c->exit_event == e); - m->quit(m, 0); + pa_core_exit(c, TRUE, 0); } -void pa_core_check_quit(pa_core *c) { +void pa_core_check_idle(pa_core *c) { pa_assert(c); - if (!c->quit_event && + if (!c->exit_event && c->exit_idle_time >= 0 && pa_idxset_size(c->clients) == 0) { @@ -217,10 +218,20 @@ void pa_core_check_quit(pa_core *c) { pa_gettimeofday(&tv); tv.tv_sec+= c->exit_idle_time; - c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c); + c->exit_event = c->mainloop->time_new(c->mainloop, &tv, exit_callback, c); - } else if (c->quit_event && pa_idxset_size(c->clients) > 0) { - c->mainloop->time_free(c->quit_event); - c->quit_event = NULL; + } else if (c->exit_event && pa_idxset_size(c->clients) > 0) { + c->mainloop->time_free(c->exit_event); + c->exit_event = NULL; } } + +int pa_core_exit(pa_core *c, pa_bool_t force, int retval) { + pa_assert(c); + + if (c->disallow_exit && !force) + return -1; + + c->mainloop->quit(c->mainloop, retval); + return 0; +} diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index e11655ef..eb768418 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -115,11 +115,12 @@ struct pa_core { int exit_idle_time, module_idle_time, scache_idle_time; - pa_time_event *quit_event; + pa_time_event *exit_event; pa_time_event *scache_auto_unload_event; pa_bool_t disallow_module_loading:1; + pa_bool_t disallow_exit:1; pa_bool_t running_as_daemon:1; pa_bool_t realtime_scheduling:1; pa_bool_t disable_remixing:1; @@ -142,6 +143,8 @@ enum { pa_core* pa_core_new(pa_mainloop_api *m, int shared); /* Check whether noone is connected to this core */ -void pa_core_check_quit(pa_core *c); +void pa_core_check_idle(pa_core *c); + +int pa_core_exit(pa_core *c, pa_bool_t force, int retval); #endif diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index f0d8790e..b9f6f083 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1955,6 +1955,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); + int ret; pa_native_connection_assert_ref(c); pa_assert(t); @@ -1965,8 +1966,9 @@ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + ret = pa_core_exit(c->protocol->core, FALSE, 0); + CHECK_VALIDITY(c->pstream, ret >= 0, tag, PA_ERR_ACCESS); - c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0); pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */ } diff --git a/src/utils/pactl.c b/src/utils/pactl.c index f5961a1b..3f00df1b 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -607,8 +607,8 @@ static void context_state_callback(pa_context *c, void *userdata) { break; case EXIT: - pa_operation_unref(pa_context_exit_daemon(c, NULL, NULL)); - drain(); + pa_operation_unref(pa_context_exit_daemon(c, simple_callback, NULL)); + break; case LIST: actions = 8; -- cgit