add systemd socket activation

This commit is contained in:
Wim Taymans 2018-10-18 09:50:43 +02:00
parent a086fc5c0c
commit 88d6e52cc7
5 changed files with 52 additions and 31 deletions

View file

@ -317,6 +317,9 @@
/* Define to 1 if you have the <winsock2.h> header file. */ /* Define to 1 if you have the <winsock2.h> header file. */
#mesondefine HAVE_WINSOCK2_H #mesondefine HAVE_WINSOCK2_H
/* for the systemd header files */
#mesondefine HAVE_SYSTEMD_DAEMON
/* the host CPU */ /* the host CPU */
#mesondefine HOST_CPU #mesondefine HOST_CPU

View file

@ -125,6 +125,16 @@ if cc.has_function('memfd_create', prefix : '#include <sys/mman.h>', args : [ '-
cdata.set('HAVE_MEMFD_CREATE', 1) cdata.set('HAVE_MEMFD_CREATE', 1)
endif endif
if get_option('systemd')
systemd = dependency('systemd', required: false)
systemd_dep = dependency('libsystemd', required: false)
if systemd.found()
cdata.set('HAVE_SYSTEMD_DAEMON', 1)
else
warning('Systemd integration was enabled, but systemd is not available')
endif
endif
configure_file(input : 'config.h.meson', configure_file(input : 'config.h.meson',
output : 'config.h', output : 'config.h',
configuration : cdata) configuration : cdata)

View file

@ -31,11 +31,6 @@ executable('pipewire',
dependencies : [pipewire_dep], dependencies : [pipewire_dep],
) )
if get_option('systemd') if systemd.found()
systemd = dependency('systemd', required: false) subdir('systemd')
if systemd.found()
subdir('systemd')
else
warning('Systemd integration was enabled, but systemd is not available')
endif
endif endif

View file

@ -63,7 +63,7 @@ pipewire_module_protocol_native = shared_library('pipewire-module-protocol-nativ
include_directories : [configinc, spa_inc], include_directories : [configinc, spa_inc],
install : true, install : true,
install_dir : modules_install_dir, install_dir : modules_install_dir,
dependencies : [mathlib, dl_lib, pipewire_dep], dependencies : [mathlib, dl_lib, pipewire_dep, systemd_dep],
) )
pipewire_module_audio_dsp = shared_library('pipewire-module-audio-dsp', pipewire_module_audio_dsp = shared_library('pipewire-module-audio-dsp',

View file

@ -33,6 +33,10 @@
#include "config.h" #include "config.h"
#ifdef HAVE_SYSTEMD_DAEMON
#include <systemd/sd-daemon.h>
#endif
#include "pipewire/pipewire.h" #include "pipewire/pipewire.h"
#include "pipewire/private.h" #include "pipewire/private.h"
#include "pipewire/log.h" #include "pipewire/log.h"
@ -95,6 +99,7 @@ struct server {
int fd_lock; int fd_lock;
struct sockaddr_un addr; struct sockaddr_un addr;
char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN]; char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN];
bool activated;
struct pw_loop *loop; struct pw_loop *loop;
struct spa_source *source; struct spa_source *source;
@ -325,8 +330,6 @@ static bool init_socket_name(struct server *s, const char *name)
static bool lock_socket(struct server *s) static bool lock_socket(struct server *s)
{ {
struct stat socket_stat;
snprintf(s->lock_addr, sizeof(s->lock_addr), "%s%s", s->addr.sun_path, LOCK_SUFFIX); snprintf(s->lock_addr, sizeof(s->lock_addr), "%s%s", s->addr.sun_path, LOCK_SUFFIX);
s->fd_lock = open(s->lock_addr, O_CREAT | O_CLOEXEC, s->fd_lock = open(s->lock_addr, O_CREAT | O_CLOEXEC,
@ -342,15 +345,6 @@ static bool lock_socket(struct server *s)
s->lock_addr); s->lock_addr);
goto err_fd; goto err_fd;
} }
if (stat(s->addr.sun_path, &socket_stat) < 0) {
if (errno != ENOENT) {
pw_log_error("did not manage to stat file %s\n", s->addr.sun_path);
goto err_fd;
}
} else if (socket_stat.st_mode & S_IWUSR || socket_stat.st_mode & S_IWGRP) {
unlink(s->addr.sun_path);
}
return true; return true;
err_fd: err_fd:
@ -394,24 +388,43 @@ socket_data(void *data, int fd, enum spa_io mask)
static bool add_socket(struct pw_protocol *protocol, struct server *s) static bool add_socket(struct pw_protocol *protocol, struct server *s)
{ {
socklen_t size; socklen_t size;
int fd; int fd = -1;
bool activated = false;
if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0) #ifdef HAVE_SYSTEMD_DAEMON
goto error; {
int i, n = sd_listen_fds(0);
size = offsetof(struct sockaddr_un, sun_path) + strlen(s->addr.sun_path); for (i = 0; i < n; ++i) {
if (bind(fd, (struct sockaddr *) &s->addr, size) < 0) { if (sd_is_socket_unix(SD_LISTEN_FDS_START + i, SOCK_STREAM,
pw_log_error("bind() failed with error: %m"); 1, s->addr.sun_path, 0) > 0) {
goto error_close; fd = SD_LISTEN_FDS_START + i;
activated = true;
pw_log_info("Found socket activation socket for '%s'", s->addr.sun_path);
break;
}
}
} }
#endif
if (listen(fd, 128) < 0) { if (fd < 0) {
pw_log_error("listen() failed with error: %m"); if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0)
goto error_close; goto error;
size = offsetof(struct sockaddr_un, sun_path) + strlen(s->addr.sun_path);
if (bind(fd, (struct sockaddr *) &s->addr, size) < 0) {
pw_log_error("bind() failed with error: %m");
goto error_close;
}
if (listen(fd, 128) < 0) {
pw_log_error("listen() failed with error: %m");
goto error_close;
}
} }
s->loop = pw_core_get_main_loop(protocol->core); s->loop = pw_core_get_main_loop(protocol->core);
s->source = pw_loop_add_io(s->loop, fd, SPA_IO_IN, true, socket_data, s); s->source = pw_loop_add_io(s->loop, fd, SPA_IO_IN, true, socket_data, s);
s->activated = activated;
if (s->source == NULL) if (s->source == NULL)
goto error_close; goto error_close;
@ -645,7 +658,7 @@ static void destroy_server(struct pw_protocol_server *server)
spa_hook_remove(&s->hook); spa_hook_remove(&s->hook);
pw_loop_destroy_source(s->loop, s->source); pw_loop_destroy_source(s->loop, s->source);
} }
if (s->addr.sun_path[0]) if (s->addr.sun_path[0] && !s->activated)
unlink(s->addr.sun_path); unlink(s->addr.sun_path);
if (s->lock_addr[0]) if (s->lock_addr[0])
unlink(s->lock_addr); unlink(s->lock_addr);