static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wrap_connection **conn) { DBusError error; pa_assert(c); pa_assert(conn); dbus_error_init(&error); if (!(*conn = pa_dbus_wrap_connection_new(c->mainloop, c->use_rtclock, type, &error)) || dbus_error_is_set(&error)) { pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message); goto fail; } if (!dbus_connection_add_filter(pa_dbus_wrap_connection_get(*conn), filter_cb, c, NULL)) { pa_log_warn("Failed to add filter function"); goto fail; } c->filter_added = TRUE; if (pa_dbus_add_matches( pa_dbus_wrap_connection_get(*conn), &error, "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',arg0='org.pulseaudio.Server',arg1=''", NULL) < 0) { pa_log_warn("Unable to track org.pulseaudio.Server: %s: %s", error.name, error.message); goto fail; } return; fail: if (*conn) { pa_dbus_wrap_connection_free(*conn); *conn = NULL; } dbus_error_free(&error); }
static int context_autospawn(pa_context *c) { pid_t pid; int status, r; struct sigaction sa; pa_context_ref(c); if (sigaction(SIGCHLD, NULL, &sa) < 0) { pa_log_debug("sigaction() failed: %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } #ifdef SA_NOCLDWAIT if ((sa.sa_flags & SA_NOCLDWAIT) || sa.sa_handler == SIG_IGN) { #else if (sa.sa_handler == SIG_IGN) { #endif pa_log_debug("Process disabled waitpid(), cannot autospawn."); pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); goto fail; } pa_log_debug("Trying to autospawn..."); if (c->spawn_api.prefork) c->spawn_api.prefork(); if ((pid = fork()) < 0) { pa_log_error(_("fork(): %s"), pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); if (c->spawn_api.postfork) c->spawn_api.postfork(); goto fail; } else if (!pid) { /* Child */ const char *state = NULL; const char * argv[32]; unsigned n = 0; if (c->spawn_api.atfork) c->spawn_api.atfork(); /* We leave most of the cleaning up of the process environment * to the executable. We only clean up the file descriptors to * make sure the executable can actually be loaded * correctly. */ pa_close_all(-1); /* Setup argv */ argv[n++] = c->conf->daemon_binary; argv[n++] = "--start"; while (n < PA_ELEMENTSOF(argv)-1) { char *a; if (!(a = pa_split_spaces(c->conf->extra_arguments, &state))) break; argv[n++] = a; } argv[n++] = NULL; pa_assert(n <= PA_ELEMENTSOF(argv)); execv(argv[0], (char * const *) argv); _exit(1); } /* Parent */ if (c->spawn_api.postfork) c->spawn_api.postfork(); do { r = waitpid(pid, &status, 0); } while (r < 0 && errno == EINTR); if (r < 0) { if (errno != ESRCH) { pa_log(_("waitpid(): %s"), pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } /* hmm, something already reaped our child, so we assume * startup worked, even if we cannot know */ } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); goto fail; } pa_context_unref(c); return 0; fail: pa_context_unref(c); return -1; } #endif /* OS_IS_WIN32 */ static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata); #ifdef HAVE_DBUS static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wrap_connection **conn) { DBusError error; pa_assert(c); pa_assert(conn); dbus_error_init(&error); if (!(*conn = pa_dbus_wrap_connection_new(c->mainloop, c->use_rtclock, type, &error)) || dbus_error_is_set(&error)) { pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message); goto fail; } if (!dbus_connection_add_filter(pa_dbus_wrap_connection_get(*conn), filter_cb, c, NULL)) { pa_log_warn("Failed to add filter function"); goto fail; } c->filter_added = true; if (pa_dbus_add_matches( pa_dbus_wrap_connection_get(*conn), &error, "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',arg0='org.pulseaudio.Server',arg1=''", NULL) < 0) { pa_log_warn("Unable to track org.pulseaudio.Server: %s: %s", error.name, error.message); goto fail; } return; fail: if (*conn) { pa_dbus_wrap_connection_free(*conn); *conn = NULL; } dbus_error_free(&error); }