summaryrefslogtreecommitdiffstats
path: root/src/daemon/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/main.c')
-rw-r--r--src/daemon/main.c111
1 files changed, 88 insertions, 23 deletions
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 789d104b..14594416 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -96,6 +94,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;
@@ -202,6 +202,13 @@ static int change_user(void) {
return -1;
}
+ if (pa_make_secure_dir(PA_SYSTEM_STATE_PATH, 0700, pw->pw_uid, gr->gr_gid) < 0) {
+ pa_log("Failed to create '%s': %s", PA_SYSTEM_STATE_PATH, pa_cstrerror(errno));
+ return -1;
+ }
+
+ /* We don't create the config dir here, because we don't need to write to it */
+
if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) {
pa_log("Failed to change group list: %s", pa_cstrerror(errno));
return -1;
@@ -246,7 +253,8 @@ static int change_user(void) {
/* Relevant for pa_runtime_path() */
pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
- pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_RUNTIME_PATH);
+ pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);
+ pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
pa_log_info("Successfully dropped root privileges.");
@@ -336,6 +344,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__)
/*
@@ -364,7 +374,7 @@ int main(int argc, char *argv[]) {
suid_root = FALSE;
#endif
- if (suid_root) {
+ if (!real_root) {
/* Drop all capabilities except CAP_SYS_NICE */
pa_limit_caps();
@@ -416,20 +426,26 @@ int main(int argc, char *argv[]) {
pa_log_set_maximal_level(conf->log_level);
pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL);
- if (suid_root) {
- pa_bool_t allow_realtime, allow_high_priority;
+ pa_log_debug("Started as real root: %s, suid root: %s", pa_yes_no(real_root), pa_yes_no(suid_root));
+
+ if (!real_root && pa_have_caps()) {
+ pa_bool_t allow_high_priority = FALSE, allow_realtime = FALSE;
- /* Ok, we're suid root, so let's better not enable high prio
- * or RT by default */
+ /* Let's better not enable high prio or RT by default */
- allow_high_priority = allow_realtime = FALSE;
+ if (conf->high_priority && !allow_high_priority) {
+ if (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) > 0) {
+ pa_log_info("We're in the group '"PA_REALTIME_GROUP"', allowing high-priority scheduling.");
+ allow_high_priority = TRUE;
+ }
+ }
- if (conf->high_priority || conf->realtime_scheduling)
+ if (conf->realtime_scheduling && !allow_realtime) {
if (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) > 0) {
- pa_log_info("We're in the group '"PA_REALTIME_GROUP"', allowing real-time and high-priority scheduling.");
- allow_realtime = conf->realtime_scheduling;
- allow_high_priority = conf->high_priority;
+ pa_log_info("We're in the group '"PA_REALTIME_GROUP"', allowing real-time scheduling.");
+ allow_realtime = TRUE;
}
+ }
#ifdef HAVE_POLKIT
if (conf->high_priority && !allow_high_priority) {
@@ -455,7 +471,6 @@ int main(int argc, char *argv[]) {
* let's give it up early */
pa_drop_caps();
- suid_root = FALSE;
if (conf->high_priority || conf->realtime_scheduling)
pa_log_notice("Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n"
@@ -478,13 +493,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) {
+ if (pa_have_caps()) {
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) {
@@ -520,6 +535,8 @@ int main(int argc, char *argv[]) {
if (conf->realtime_scheduling && !pa_can_realtime())
pa_log_warn("Real-time scheduling enabled in configuration but not allowed by policy.");
+ pa_log_debug("Can realtime: %s, can high-priority: %s", pa_yes_no(pa_can_realtime()), pa_yes_no(pa_can_high_priority()));
+
LTDL_SET_PRELOADED_SYMBOLS();
pa_ltdl_init();
ltdl_init = TRUE;
@@ -600,7 +617,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)
@@ -610,6 +627,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;
@@ -653,6 +679,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
@@ -705,13 +739,35 @@ int main(int argc, char *argv[]) {
if (change_user() < 0)
goto finish;
+ pa_set_env("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
+
pa_log_info("This is PulseAudio " PACKAGE_VERSION);
pa_log_info("Page size is %lu bytes", (unsigned long) PA_PAGE_SIZE);
- pa_log_info("Using runtime directory %s.", s = pa_get_runtime_dir());
+ if (!(s = pa_get_runtime_dir()))
+ goto finish;
+ pa_log_info("Using runtime directory %s.", s);
pa_xfree(s);
+ if (!(s = pa_get_state_dir()))
+ pa_log_info("Using state directory %s.", s);
+ pa_xfree(s);
+
+ 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() < 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;
}
@@ -740,7 +796,6 @@ int main(int argc, char *argv[]) {
goto finish;
}
- c->is_system_instance = !!conf->system_instance;
c->default_sample_spec = conf->default_sample_spec;
c->default_n_fragments = conf->default_n_fragments;
c->default_fragment_size_msec = conf->default_fragment_size_msec;
@@ -810,11 +865,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
@@ -828,6 +884,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);
@@ -844,6 +906,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