mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
socket-server: Add support for systemd socket activation.
This adds support to module-native-protocol-unix to take over already listening sockets passed in via socket activation (e.g. from systemd) Most of the code is isolated to socket-server but some cleanup code also had to be tweaked to ensure we do not overzealously close open fds.
This commit is contained in:
parent
fb1ca6f0c1
commit
467b4b9bee
5 changed files with 116 additions and 29 deletions
21
configure.ac
21
configure.ac
|
|
@ -1180,6 +1180,9 @@ ORC_CHECK([0.4.11])
|
||||||
|
|
||||||
#### systemd support (optional) ####
|
#### systemd support (optional) ####
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([systemd-daemon],
|
||||||
|
AS_HELP_STRING([--disable-systemd-daemon],[Disable optional systemd daemon (socket activation) support]))
|
||||||
|
|
||||||
AC_ARG_ENABLE([systemd-login],
|
AC_ARG_ENABLE([systemd-login],
|
||||||
AS_HELP_STRING([--disable-systemd-login],[Disable optional systemd login support]))
|
AS_HELP_STRING([--disable-systemd-login],[Disable optional systemd login support]))
|
||||||
|
|
||||||
|
|
@ -1189,16 +1192,30 @@ AC_ARG_ENABLE([systemd-journal],
|
||||||
# Newer systemd's combine their subcomponent libraries into one
|
# Newer systemd's combine their subcomponent libraries into one
|
||||||
# If it exists, we should use it for the further checks
|
# If it exists, we should use it for the further checks
|
||||||
|
|
||||||
AS_IF([test "x$enable_systemd_login" != "xno" || test "x$enable_systemd_journal" != "xno"],
|
AS_IF([test "x$enable_systemd_daemon" != "xno" || test "x$enable_systemd_login" != "xno" || test "x$enable_systemd_journal" != "xno"],
|
||||||
[PKG_CHECK_MODULES(SYSTEMD, [ libsystemd ], HAVE_SYSTEMD=1, HAVE_SYSTEMD=0)],
|
[PKG_CHECK_MODULES(SYSTEMD, [ libsystemd ], HAVE_SYSTEMD=1, HAVE_SYSTEMD=0)],
|
||||||
HAVE_SYSTEMD=0)
|
HAVE_SYSTEMD=0)
|
||||||
|
|
||||||
AS_IF([test "x$HAVE_SYSTEMD" = "x1"],
|
AS_IF([test "x$HAVE_SYSTEMD" = "x1"],
|
||||||
[
|
[
|
||||||
|
HAVE_SYSTEMD_DAEMON=1
|
||||||
HAVE_SYSTEMD_LOGIN=1
|
HAVE_SYSTEMD_LOGIN=1
|
||||||
HAVE_SYSTEMD_JOURNAL=1
|
HAVE_SYSTEMD_JOURNAL=1
|
||||||
])
|
])
|
||||||
|
|
||||||
|
#### systemd daemon support (optional) ####
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_systemd_daemon" != "xno"],
|
||||||
|
[AS_IF([test "x$HAVE_SYSTEMD_DAEMON" != "x1"], [PKG_CHECK_MODULES(SYSTEMDDAEMON, [ libsystemd-daemon ], HAVE_SYSTEMD_DAEMON=1, HAVE_SYSTEMD_DAEMON=0)])],
|
||||||
|
HAVE_SYSTEMD_DAEMON=0)
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_systemd_daemon" = "xyes" && test "x$HAVE_SYSTEMD_DAEMON" = "x0"],
|
||||||
|
[AC_MSG_ERROR([*** Needed systemd daemon support not found])])
|
||||||
|
|
||||||
|
AC_SUBST(HAVE_SYSTEMD_DAEMON)
|
||||||
|
AM_CONDITIONAL([HAVE_SYSTEMD_DAEMON], [test "x$HAVE_SYSTEMD_DAEMON" = x1])
|
||||||
|
AS_IF([test "x$HAVE_SYSTEMD_DAEMON" = "x1"], AC_DEFINE([HAVE_SYSTEMD_DAEMON], 1, [Have SYSTEMDDAEMON?]))
|
||||||
|
|
||||||
#### systemd login support (optional) ####
|
#### systemd login support (optional) ####
|
||||||
|
|
||||||
AS_IF([test "x$enable_systemd_login" != "xno"],
|
AS_IF([test "x$enable_systemd_login" != "xno"],
|
||||||
|
|
@ -1473,6 +1490,7 @@ AS_IF([test "x$HAVE_LIRC" = "x1"], ENABLE_LIRC=yes, ENABLE_LIRC=no)
|
||||||
AS_IF([test "x$HAVE_XEN" = "x1"], ENABLE_XEN=yes, ENABLE_XEN=no)
|
AS_IF([test "x$HAVE_XEN" = "x1"], ENABLE_XEN=yes, ENABLE_XEN=no)
|
||||||
AS_IF([test "x$HAVE_DBUS" = "x1"], ENABLE_DBUS=yes, ENABLE_DBUS=no)
|
AS_IF([test "x$HAVE_DBUS" = "x1"], ENABLE_DBUS=yes, ENABLE_DBUS=no)
|
||||||
AS_IF([test "x$HAVE_UDEV" = "x1"], ENABLE_UDEV=yes, ENABLE_UDEV=no)
|
AS_IF([test "x$HAVE_UDEV" = "x1"], ENABLE_UDEV=yes, ENABLE_UDEV=no)
|
||||||
|
AS_IF([test "x$HAVE_SYSTEMD_DAEMON" = "x1"], ENABLE_SYSTEMD_DAEMON=yes, ENABLE_SYSTEMD_DAEMON=no)
|
||||||
AS_IF([test "x$HAVE_SYSTEMD_LOGIN" = "x1"], ENABLE_SYSTEMD_LOGIN=yes, ENABLE_SYSTEMD_LOGIN=no)
|
AS_IF([test "x$HAVE_SYSTEMD_LOGIN" = "x1"], ENABLE_SYSTEMD_LOGIN=yes, ENABLE_SYSTEMD_LOGIN=no)
|
||||||
AS_IF([test "x$HAVE_SYSTEMD_JOURNAL" = "x1"], ENABLE_SYSTEMD_JOURNAL=yes, ENABLE_SYSTEMD_JOURNAL=no)
|
AS_IF([test "x$HAVE_SYSTEMD_JOURNAL" = "x1"], ENABLE_SYSTEMD_JOURNAL=yes, ENABLE_SYSTEMD_JOURNAL=no)
|
||||||
AS_IF([test "x$HAVE_BLUEZ_4" = "x1"], ENABLE_BLUEZ_4=yes, ENABLE_BLUEZ_4=no)
|
AS_IF([test "x$HAVE_BLUEZ_4" = "x1"], ENABLE_BLUEZ_4=yes, ENABLE_BLUEZ_4=no)
|
||||||
|
|
@ -1534,6 +1552,7 @@ echo "
|
||||||
headset backend: ${BLUETOOTH_HEADSET_BACKEND}
|
headset backend: ${BLUETOOTH_HEADSET_BACKEND}
|
||||||
Enable udev: ${ENABLE_UDEV}
|
Enable udev: ${ENABLE_UDEV}
|
||||||
Enable HAL->udev compat: ${ENABLE_HAL_COMPAT}
|
Enable HAL->udev compat: ${ENABLE_HAL_COMPAT}
|
||||||
|
Enable systemd daemon: ${ENABLE_SYSTEMD_DAEMON}
|
||||||
Enable systemd login: ${ENABLE_SYSTEMD_LOGIN}
|
Enable systemd login: ${ENABLE_SYSTEMD_LOGIN}
|
||||||
Enable systemd journal: ${ENABLE_SYSTEMD_JOURNAL}
|
Enable systemd journal: ${ENABLE_SYSTEMD_JOURNAL}
|
||||||
Enable TCP Wrappers: ${ENABLE_TCPWRAP}
|
Enable TCP Wrappers: ${ENABLE_TCPWRAP}
|
||||||
|
|
|
||||||
|
|
@ -706,6 +706,10 @@ libpulsecommon_@PA_MAJORMINOR@_la_CFLAGS += $(X11_CFLAGS)
|
||||||
libpulsecommon_@PA_MAJORMINOR@_la_LDFLAGS += $(X11_LIBS)
|
libpulsecommon_@PA_MAJORMINOR@_la_LDFLAGS += $(X11_LIBS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if HAVE_SYSTEMD_DAEMON
|
||||||
|
libpulsecommon_@PA_MAJORMINOR@_la_CFLAGS += $(SYSTEMD_FLAGS) $(SYSTEMDDAEMON_FLAGS)
|
||||||
|
libpulsecommon_@PA_MAJORMINOR@_la_LDFLAGS += $(SYSTEMD_LIBS) $(SYSTEMDDAEMON_LIBS)
|
||||||
|
endif
|
||||||
if HAVE_SYSTEMD_JOURNAL
|
if HAVE_SYSTEMD_JOURNAL
|
||||||
libpulsecommon_@PA_MAJORMINOR@_la_CFLAGS += $(SYSTEMD_FLAGS) $(SYSTEMDJOURNAL_FLAGS)
|
libpulsecommon_@PA_MAJORMINOR@_la_CFLAGS += $(SYSTEMD_FLAGS) $(SYSTEMDJOURNAL_FLAGS)
|
||||||
libpulsecommon_@PA_MAJORMINOR@_la_LDFLAGS += $(SYSTEMD_LIBS) $(SYSTEMDJOURNAL_LIBS)
|
libpulsecommon_@PA_MAJORMINOR@_la_LDFLAGS += $(SYSTEMD_LIBS) $(SYSTEMDJOURNAL_LIBS)
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,10 @@
|
||||||
#include <dbus/dbus.h>
|
#include <dbus/dbus.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSTEMD_DAEMON
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pulse/client-conf.h>
|
#include <pulse/client-conf.h>
|
||||||
#include <pulse/mainloop.h>
|
#include <pulse/mainloop.h>
|
||||||
#include <pulse/mainloop-signal.h>
|
#include <pulse/mainloop-signal.h>
|
||||||
|
|
@ -374,7 +378,7 @@ int main(int argc, char *argv[]) {
|
||||||
int r = 0, retval = 1, d = 0;
|
int r = 0, retval = 1, d = 0;
|
||||||
bool valid_pid_file = false;
|
bool valid_pid_file = false;
|
||||||
bool ltdl_init = false;
|
bool ltdl_init = false;
|
||||||
int passed_fd = -1;
|
int n_fds = 0, *passed_fds = NULL;
|
||||||
const char *e;
|
const char *e;
|
||||||
#ifdef HAVE_FORK
|
#ifdef HAVE_FORK
|
||||||
int daemon_pipe[2] = { -1, -1 };
|
int daemon_pipe[2] = { -1, -1 };
|
||||||
|
|
@ -431,11 +435,28 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((e = getenv("PULSE_PASSED_FD"))) {
|
#ifdef HAVE_SYSTEMD_DAEMON
|
||||||
passed_fd = atoi(e);
|
n_fds = sd_listen_fds(0);
|
||||||
|
if (n_fds > 0) {
|
||||||
|
int i = n_fds;
|
||||||
|
|
||||||
if (passed_fd <= 2)
|
passed_fds = pa_xnew(int, n_fds+2);
|
||||||
passed_fd = -1;
|
passed_fds[n_fds] = passed_fds[n_fds+1] = -1;
|
||||||
|
while (i--)
|
||||||
|
passed_fds[i] = SD_LISTEN_FDS_START + i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!passed_fds) {
|
||||||
|
n_fds = 0;
|
||||||
|
passed_fds = pa_xnew(int, 2);
|
||||||
|
passed_fds[0] = passed_fds[1] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((e = getenv("PULSE_PASSED_FD"))) {
|
||||||
|
int passed_fd = atoi(e);
|
||||||
|
if (passed_fd > 2)
|
||||||
|
passed_fds[n_fds] = passed_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We might be autospawned, in which case have no idea in which
|
/* We might be autospawned, in which case have no idea in which
|
||||||
|
|
@ -444,7 +465,8 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
pa_reset_personality();
|
pa_reset_personality();
|
||||||
pa_drop_root();
|
pa_drop_root();
|
||||||
pa_close_all(passed_fd, -1);
|
pa_close_allv(passed_fds);
|
||||||
|
pa_xfree(passed_fds);
|
||||||
pa_reset_sigs(-1);
|
pa_reset_sigs(-1);
|
||||||
pa_unblock_sigs(-1);
|
pa_unblock_sigs(-1);
|
||||||
pa_reset_priority();
|
pa_reset_priority();
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,10 @@ int deny_severity = LOG_WARNING;
|
||||||
|
|
||||||
#endif /* HAVE_LIBWRAP */
|
#endif /* HAVE_LIBWRAP */
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSTEMD_DAEMON
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pulse/xmalloc.h>
|
#include <pulse/xmalloc.h>
|
||||||
#include <pulse/util.h>
|
#include <pulse/util.h>
|
||||||
|
|
||||||
|
|
@ -74,6 +78,7 @@ struct pa_socket_server {
|
||||||
PA_REFCNT_DECLARE;
|
PA_REFCNT_DECLARE;
|
||||||
int fd;
|
int fd;
|
||||||
char *filename;
|
char *filename;
|
||||||
|
bool activated;
|
||||||
char *tcpwrap_service;
|
char *tcpwrap_service;
|
||||||
|
|
||||||
pa_socket_server_on_connection_cb_t on_connection;
|
pa_socket_server_on_connection_cb_t on_connection;
|
||||||
|
|
@ -174,43 +179,63 @@ pa_socket_server* pa_socket_server_ref(pa_socket_server *s) {
|
||||||
|
|
||||||
pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename) {
|
pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename) {
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
bool activated = false;
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
pa_socket_server *s;
|
pa_socket_server *s;
|
||||||
|
|
||||||
pa_assert(m);
|
pa_assert(m);
|
||||||
pa_assert(filename);
|
pa_assert(filename);
|
||||||
|
|
||||||
if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
#ifdef HAVE_SYSTEMD_DAEMON
|
||||||
pa_log("socket(): %s", pa_cstrerror(errno));
|
{
|
||||||
goto fail;
|
int n = sd_listen_fds(0);
|
||||||
|
if (n > 0) {
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
if (sd_is_socket_unix(SD_LISTEN_FDS_START + i, SOCK_STREAM, 1, filename, 0) > 0) {
|
||||||
|
fd = SD_LISTEN_FDS_START + i;
|
||||||
|
activated = true;
|
||||||
|
pa_log_info("Found socket activation socket for '%s' \\o/", filename);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
if (fd < 0) {
|
||||||
sa.sun_family = AF_UNIX;
|
if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||||
pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
|
pa_log("socket(PF_UNIX): %s", pa_cstrerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
pa_make_socket_low_delay(fd);
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.sun_family = AF_UNIX;
|
||||||
|
pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
|
||||||
|
|
||||||
if (bind(fd, (struct sockaddr*) &sa, (socklen_t) SUN_LEN(&sa)) < 0) {
|
pa_make_socket_low_delay(fd);
|
||||||
pa_log("bind(): %s", pa_cstrerror(errno));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allow access from all clients. Sockets like this one should
|
if (bind(fd, (struct sockaddr*) &sa, (socklen_t) SUN_LEN(&sa)) < 0) {
|
||||||
* always be put inside a directory with proper access rights,
|
pa_log("bind(): %s", pa_cstrerror(errno));
|
||||||
* because not all OS check the access rights on the socket
|
goto fail;
|
||||||
* inodes. */
|
}
|
||||||
chmod(filename, 0777);
|
|
||||||
|
|
||||||
if (listen(fd, 5) < 0) {
|
/* Allow access from all clients. Sockets like this one should
|
||||||
pa_log("listen(): %s", pa_cstrerror(errno));
|
* always be put inside a directory with proper access rights,
|
||||||
goto fail;
|
* because not all OS check the access rights on the socket
|
||||||
|
* inodes. */
|
||||||
|
chmod(filename, 0777);
|
||||||
|
|
||||||
|
if (listen(fd, 5) < 0) {
|
||||||
|
pa_log("listen(): %s", pa_cstrerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_assert_se(s = pa_socket_server_new(m, fd));
|
pa_assert_se(s = pa_socket_server_new(m, fd));
|
||||||
|
|
||||||
s->filename = pa_xstrdup(filename);
|
s->filename = pa_xstrdup(filename);
|
||||||
s->type = SOCKET_SERVER_UNIX;
|
s->type = SOCKET_SERVER_UNIX;
|
||||||
|
s->activated = activated;
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
|
|
@ -421,10 +446,9 @@ pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const cha
|
||||||
static void socket_server_free(pa_socket_server*s) {
|
static void socket_server_free(pa_socket_server*s) {
|
||||||
pa_assert(s);
|
pa_assert(s);
|
||||||
|
|
||||||
if (s->filename) {
|
if (!s->activated && s->filename)
|
||||||
unlink(s->filename);
|
unlink(s->filename);
|
||||||
pa_xfree(s->filename);
|
pa_xfree(s->filename);
|
||||||
}
|
|
||||||
|
|
||||||
pa_close(s->fd);
|
pa_close(s->fd);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,9 @@
|
||||||
#ifdef HAVE_NETDB_H
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYSTEMD_DAEMON
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pulsecore/core-error.h>
|
#include <pulsecore/core-error.h>
|
||||||
#include <pulsecore/core-util.h>
|
#include <pulsecore/core-util.h>
|
||||||
|
|
@ -255,6 +258,21 @@ int pa_unix_socket_remove_stale(const char *fn) {
|
||||||
|
|
||||||
pa_assert(fn);
|
pa_assert(fn);
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSTEMD_DAEMON
|
||||||
|
{
|
||||||
|
int n = sd_listen_fds(0);
|
||||||
|
if (n > 0) {
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
if (sd_is_socket_unix(SD_LISTEN_FDS_START + i, SOCK_STREAM, 1, fn, 0) > 0) {
|
||||||
|
/* This is a socket activated socket, therefore do not consider
|
||||||
|
* it stale. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((r = pa_unix_socket_is_stale(fn)) < 0)
|
if ((r = pa_unix_socket_is_stale(fn)) < 0)
|
||||||
return errno != ENOENT ? -1 : 0;
|
return errno != ENOENT ? -1 : 0;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue