mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
pulse-server: alsa safely make native socket
Only make the native socket when it's not there or when it appears dead when we can't seem to connect to it. - When the socket is not found, we take it. - When an existing pulseaudio is running we won't unlink and take over the socket because we can connect to it - When a crashed pulseaudio leaves a stale socket, we fail to connect and then we unlink and take over.
This commit is contained in:
parent
1d001974d7
commit
6e2ab9973b
1 changed files with 48 additions and 14 deletions
|
|
@ -4390,9 +4390,20 @@ get_server_name(struct pw_context *context)
|
|||
return name;
|
||||
}
|
||||
|
||||
static int check_connect(struct server *server, int fd)
|
||||
{
|
||||
int res;
|
||||
socklen_t size;
|
||||
|
||||
size = offsetof(struct sockaddr_un, sun_path) + strlen(server->addr.sun_path);
|
||||
if ((res = connect(fd, (struct sockaddr *)&server->addr, size)) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_local_socket(struct server *server, char *name)
|
||||
{
|
||||
struct impl *impl = server->impl;
|
||||
char runtime_dir[PATH_MAX];
|
||||
socklen_t size;
|
||||
int name_size, fd, res;
|
||||
|
|
@ -4403,8 +4414,7 @@ static int make_local_socket(struct server *server, char *name)
|
|||
|
||||
server->addr.sun_family = AF_LOCAL;
|
||||
name_size = snprintf(server->addr.sun_path, sizeof(server->addr.sun_path),
|
||||
"%s/%s-%s", runtime_dir, name,
|
||||
get_server_name(impl->context)) + 1;
|
||||
"%s/%s", runtime_dir, name) + 1;
|
||||
|
||||
if (name_size > (int) sizeof(server->addr.sun_path)) {
|
||||
pw_log_error(NAME" %p: %s/%s too long",
|
||||
|
|
@ -4412,6 +4422,8 @@ static int make_local_socket(struct server *server, char *name)
|
|||
res = -ENAMETOOLONG;
|
||||
goto error;
|
||||
}
|
||||
size = offsetof(struct sockaddr_un, sun_path) + strlen(server->addr.sun_path);
|
||||
|
||||
if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0) {
|
||||
res = -errno;
|
||||
goto error;
|
||||
|
|
@ -4419,15 +4431,24 @@ static int make_local_socket(struct server *server, char *name)
|
|||
if (stat(server->addr.sun_path, &socket_stat) < 0) {
|
||||
if (errno != ENOENT) {
|
||||
res = -errno;
|
||||
pw_log_error("server %p: stat %s failed with error: %m",
|
||||
pw_log_error(NAME" %p: stat %s failed with error: %m",
|
||||
server, server->addr.sun_path);
|
||||
goto error_close;
|
||||
}
|
||||
} else if (socket_stat.st_mode & S_IWUSR || socket_stat.st_mode & S_IWGRP) {
|
||||
unlink(server->addr.sun_path);
|
||||
/* socket is there, check if we can connect */
|
||||
if ((res = check_connect(server, fd)) < 0) {
|
||||
/* we can't connect, probably stale, remove it */
|
||||
pw_log_warn(NAME" %p: unlink stale socket %s: %s", server,
|
||||
server->addr.sun_path, spa_strerror(res));
|
||||
unlink(server->addr.sun_path);
|
||||
} else {
|
||||
/* we could connect so it's probably in use */
|
||||
pw_log_info(NAME" %p: socket %s is in use", server,
|
||||
server->addr.sun_path);
|
||||
goto error_close;
|
||||
}
|
||||
}
|
||||
|
||||
size = offsetof(struct sockaddr_un, sun_path) + strlen(server->addr.sun_path);
|
||||
if (bind(fd, (struct sockaddr *) &server->addr, size) < 0) {
|
||||
res = -errno;
|
||||
pw_log_error(NAME" %p: bind() to %s failed with error: %m", server,
|
||||
|
|
@ -4584,12 +4605,24 @@ struct pw_protocol_pulse *pw_protocol_pulse_new(struct pw_context *context,
|
|||
struct impl *impl;
|
||||
const char *str;
|
||||
int i, n_addr;
|
||||
char **addr;
|
||||
char **addr, *free_str = NULL;
|
||||
|
||||
impl = calloc(1, sizeof(struct impl) + user_data_size);
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
str = NULL;
|
||||
if (props != NULL)
|
||||
str = pw_properties_get(props, "server.address");
|
||||
if (str == NULL) {
|
||||
str = free_str = spa_aprintf("%s,%s-%s",
|
||||
PW_PROTOCOL_PULSE_DEFAULT_SERVER,
|
||||
PW_PROTOCOL_PULSE_DEFAULT_SERVER,
|
||||
get_server_name(context));
|
||||
}
|
||||
if (str == NULL)
|
||||
goto error_free;
|
||||
|
||||
debug_messages = pw_debug_is_category_enabled("connection");
|
||||
|
||||
impl->context = context;
|
||||
|
|
@ -4602,22 +4635,23 @@ struct pw_protocol_pulse *pw_protocol_pulse_new(struct pw_context *context,
|
|||
pw_context_add_listener(context, &impl->context_listener,
|
||||
&context_events, impl);
|
||||
|
||||
str = NULL;
|
||||
if (props != NULL)
|
||||
str = pw_properties_get(props, "server.address");
|
||||
if (str == NULL)
|
||||
str = PW_PROTOCOL_PULSE_DEFAULT_SERVER;
|
||||
|
||||
addr = pw_split_strv(str, ",", INT_MAX, &n_addr);
|
||||
for (i = 0; i < n_addr; i++) {
|
||||
if (addr[i] == NULL)
|
||||
continue;
|
||||
if (create_server(impl, addr[i]) == NULL) {
|
||||
pw_log_warn(NAME" %p: can't create server for %s: %m",
|
||||
impl, addr[i]);
|
||||
}
|
||||
}
|
||||
pw_free_strv(addr);
|
||||
free(free_str);
|
||||
|
||||
return (struct pw_protocol_pulse*)impl;
|
||||
|
||||
error_free:
|
||||
free(impl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *pw_protocol_pulse_get_user_data(struct pw_protocol_pulse *pulse)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue