diff options
-rw-r--r-- | man/pulseaudio.1.xml.in | 11 | ||||
-rw-r--r-- | src/daemon/cmdline.c | 10 | ||||
-rw-r--r-- | src/daemon/daemon-conf.h | 1 | ||||
-rw-r--r-- | src/daemon/main.c | 56 | ||||
-rw-r--r-- | src/pulsecore/pid.c | 1 |
5 files changed, 72 insertions, 7 deletions
diff --git a/man/pulseaudio.1.xml.in b/man/pulseaudio.1.xml.in index 1f53a60b..5988c12d 100644 --- a/man/pulseaudio.1.xml.in +++ b/man/pulseaudio.1.xml.in @@ -33,6 +33,7 @@ USA. <cmd>pulseaudio <opt>--dump-modules</opt></cmd> <cmd>pulseaudio <opt>--dump-resample-methods</opt></cmd> <cmd>pulseaudio <opt>--cleanup-shm</opt></cmd> + <cmd>pulseaudio <opt>--start</opt></cmd> <cmd>pulseaudio <opt>--kill</opt></cmd> <cmd>pulseaudio <opt>--check</opt></cmd> </synopsis> @@ -91,6 +92,16 @@ USA. </option> <option> + <p><opt>--start</opt></p> + + <optdesc><p>Start PulseAudio if it is not running yet. This is + different from starting PulseAudio without <opt>--start</opt> + which would fail if PA is already running. PulseAudio is + guaranteed to be fully initialized when this call + returns. Implies <opt>--daemon</p>.</optdesc> + </option> + + <option> <p><opt>-k | --kill</opt></p> <optdesc><p>Kill an already running PulseAudio daemon of the diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index 97c75f37..03b1ac78 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -66,7 +66,8 @@ enum { ARG_DISABLE_SHM, ARG_DUMP_RESAMPLE_METHODS, ARG_SYSTEM, - ARG_CLEANUP_SHM + ARG_CLEANUP_SHM, + ARG_START }; /* Tabel for getopt_long() */ @@ -91,6 +92,7 @@ static const struct option long_options[] = { {"dl-search-path", 1, 0, ARG_DL_SEARCH_PATH}, {"resample-method", 1, 0, ARG_RESAMPLE_METHOD}, {"kill", 0, 0, ARG_KILL}, + {"start", 0, 0, ARG_START}, {"use-pid-file", 2, 0, ARG_USE_PID_FILE}, {"check", 0, 0, ARG_CHECK}, {"system", 2, 0, ARG_SYSTEM}, @@ -119,6 +121,7 @@ void pa_cmdline_help(const char *argv0) { " --dump-modules Dump list of available modules\n" " --dump-resample-methods Dump available resample methods\n" " --cleanup-shm Cleanup stale shared memory segments\n" + " --start Start the daemon if it is not running\n" " -k --kill Kill a running daemon\n" " --check Check for a running daemon\n\n" @@ -207,6 +210,11 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d conf->cmd = PA_CMD_KILL; break; + case ARG_START: + conf->cmd = PA_CMD_START; + conf->daemonize = TRUE; + break; + case ARG_CHECK: conf->cmd = PA_CMD_CHECK; break; diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index 03a75661..373924ac 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -37,6 +37,7 @@ /* The actual command to execute */ typedef enum pa_daemon_conf_cmd { PA_CMD_DAEMON, /* the default */ + PA_CMD_START, PA_CMD_HELP, PA_CMD_VERSION, PA_CMD_DUMP_CONF, diff --git a/src/daemon/main.c b/src/daemon/main.c index 6e5997cf..d4c16fef 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -96,6 +96,8 @@ #include "ltdl-bind-now.h" #include "polkit.h" +#define AUTOSPAWN_LOCK "autospawn.lock" + #ifdef HAVE_LIBWRAP /* Only one instance of these variables */ int allow_severity = LOG_INFO; @@ -344,6 +346,8 @@ int main(int argc, char *argv[]) { pa_time_event *win32_timer; struct timeval win32_tv; #endif + char *lf = NULL; + int autospawn_lock_fd = -1; #if defined(__linux__) && defined(__OPTIMIZE__) /* @@ -486,13 +490,13 @@ int main(int argc, char *argv[]) { if (conf->high_priority && !pa_can_high_priority()) pa_log_warn("High-priority scheduling enabled in configuration but not allowed by policy."); - if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) + if (conf->high_priority && (conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START)) pa_raise_priority(conf->nice_level); if (suid_root) { pa_bool_t drop; - drop = conf->cmd != PA_CMD_DAEMON || !conf->realtime_scheduling; + drop = (conf->cmd != PA_CMD_DAEMON && conf->cmd != PA_CMD_START) || !conf->realtime_scheduling; #ifdef RLIMIT_RTPRIO if (!drop) { @@ -608,7 +612,7 @@ int main(int argc, char *argv[]) { goto finish; default: - pa_assert(conf->cmd == PA_CMD_DAEMON); + pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START); } if (real_root && !conf->system_instance) @@ -618,6 +622,15 @@ int main(int argc, char *argv[]) { goto finish; } + if (conf->cmd == PA_CMD_START) { + /* If we shall start PA only when it is not running yet, we + * first take the autospawn lock to make things + * synchronous. */ + + lf = pa_runtime_path(AUTOSPAWN_LOCK); + autospawn_lock_fd = pa_lock_lockfile(lf); + } + if (conf->daemonize) { pid_t child; int tty_fd; @@ -661,6 +674,14 @@ int main(int argc, char *argv[]) { goto finish; } + if (autospawn_lock_fd >= 0) { + /* The lock file is unlocked from the parent, so we need + * to close it in the child */ + + pa_close(autospawn_lock_fd); + autospawn_lock_fd = -1; + } + pa_assert_se(pa_close(daemon_pipe[0]) == 0); daemon_pipe[0] = -1; #endif @@ -728,7 +749,20 @@ int main(int argc, char *argv[]) { pa_log_info("Running in system mode: %s", pa_yes_no(pa_in_system_mode())); if (conf->use_pid_file) { - if (pa_pid_file_create("pulseaudio") < 0) { + int z; + + if ((z = pa_pid_file_create("pulseaudio")) != 0) { + + if (conf->cmd == PA_CMD_START && z > 0) { + /* If we are already running and with are run in + * --start mode, then let's return this as success. */ + + pa_log_info("z=%i rock!", z); + + retval = 0; + goto finish; + } + pa_log("pa_pid_file_create() failed."); goto finish; } @@ -826,11 +860,12 @@ int main(int argc, char *argv[]) { goto finish; } - #ifdef HAVE_FORK - if (conf->daemonize) { + if (daemon_pipe[1] >= 0) { int ok = 0; pa_loop_write(daemon_pipe[1], &ok, sizeof(ok), NULL); + pa_close(daemon_pipe[1]); + daemon_pipe[1] = -1; } #endif @@ -844,6 +879,12 @@ int main(int argc, char *argv[]) { finish: + if (autospawn_lock_fd >= 0) + pa_unlock_lockfile(lf, autospawn_lock_fd); + + if (lf) + pa_xfree(lf); + #ifdef OS_IS_WIN32 if (win32_timer) pa_mainloop_get_api(mainloop)->time_free(win32_timer); @@ -860,6 +901,9 @@ finish: pa_signal_done(); #ifdef HAVE_FORK + if (daemon_pipe[1] >= 0) + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); + pa_close_pipe(daemon_pipe); #endif diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index 9e93234f..dd2e699d 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -220,6 +220,7 @@ int pa_pid_file_create(const char *procname) { if (ours) { pa_log("Daemon already running."); + ret = 1; goto fail; } } |