mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-08 13:29:59 -05:00
x11: gracefully handle ICE connection error
Implementation is largely inspired by GNOME/mutter ICE session handling. Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/441>
This commit is contained in:
parent
b6396dbe9c
commit
6bfd9c809e
1 changed files with 69 additions and 13 deletions
|
|
@ -55,21 +55,50 @@ struct userdata {
|
|||
pa_module *module;
|
||||
pa_client *client;
|
||||
SmcConn connection;
|
||||
pa_x11_wrapper *x11;
|
||||
|
||||
pa_x11_wrapper *x11_wrapper;
|
||||
pa_x11_client *x11_client;
|
||||
};
|
||||
|
||||
static void x11_kill_cb(pa_x11_wrapper *w, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
|
||||
pa_assert(w);
|
||||
pa_assert(u);
|
||||
pa_assert(u->x11_wrapper == w);
|
||||
|
||||
pa_log_debug("X11 client kill callback called");
|
||||
|
||||
if (u->connection) {
|
||||
SmcCloseConnection(u->connection, 0, NULL);
|
||||
u->connection = NULL;
|
||||
}
|
||||
|
||||
if (u->x11_client) {
|
||||
pa_x11_client_free(u->x11_client);
|
||||
u->x11_client = NULL;
|
||||
}
|
||||
|
||||
if (u->x11_wrapper) {
|
||||
pa_x11_wrapper_unref(u->x11_wrapper);
|
||||
u->x11_wrapper = NULL;
|
||||
}
|
||||
|
||||
pa_module_unload_request(u->module, true);
|
||||
}
|
||||
|
||||
static void die_cb(SmcConn connection, SmPointer client_data) {
|
||||
struct userdata *u = client_data;
|
||||
pa_assert(u);
|
||||
|
||||
pa_log_debug("Got die message from XSMP.");
|
||||
|
||||
pa_x11_wrapper_kill_deferred(u->x11);
|
||||
if (u->connection) {
|
||||
SmcCloseConnection(u->connection, 0, NULL);
|
||||
u->connection = NULL;
|
||||
}
|
||||
|
||||
pa_x11_wrapper_unref(u->x11);
|
||||
u->x11 = NULL;
|
||||
|
||||
pa_module_unload_request(u->module, true);
|
||||
pa_x11_wrapper_kill_deferred(u->x11_wrapper);
|
||||
}
|
||||
|
||||
static void save_complete_cb(SmcConn connection, SmPointer client_data) {
|
||||
|
|
@ -87,6 +116,7 @@ static void ice_io_cb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_fla
|
|||
IceConn connection = userdata;
|
||||
|
||||
if (IceProcessMessages(connection, NULL, NULL) == IceProcessMessagesIOError) {
|
||||
pa_log_debug("IceProcessMessages: I/O error, closing ICE connection");
|
||||
IceSetShutdownNegotiation(connection, False);
|
||||
IceCloseConnection(connection);
|
||||
}
|
||||
|
|
@ -106,6 +136,17 @@ static void new_ice_connection(IceConn connection, IcePointer client_data, Bool
|
|||
c->mainloop->io_free(*watch_data);
|
||||
}
|
||||
|
||||
static IceIOErrorHandler ice_installed_handler;
|
||||
|
||||
/* We call any handler installed before (or after) module is loaded but
|
||||
avoid calling the default libICE handler which does an exit() */
|
||||
|
||||
static void ice_io_error_handler(IceConn iceConn) {
|
||||
pa_log_warn("ICE I/O error handler called");
|
||||
if (ice_installed_handler)
|
||||
(*ice_installed_handler) (iceConn);
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
|
||||
pa_modargs *ma = NULL;
|
||||
|
|
@ -123,17 +164,27 @@ int pa__init(pa_module*m) {
|
|||
if (ice_in_use) {
|
||||
pa_log("module-x11-xsmp may not be loaded twice.");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
IceIOErrorHandler default_handler;
|
||||
|
||||
IceAddConnectionWatch(new_ice_connection, m->core);
|
||||
ice_in_use = true;
|
||||
ice_installed_handler = IceSetIOErrorHandler (NULL);
|
||||
default_handler = IceSetIOErrorHandler (ice_io_error_handler);
|
||||
|
||||
if (ice_installed_handler == default_handler)
|
||||
ice_installed_handler = NULL;
|
||||
|
||||
IceSetIOErrorHandler(ice_io_error_handler);
|
||||
|
||||
IceAddConnectionWatch(new_ice_connection, m->core);
|
||||
ice_in_use = true;
|
||||
}
|
||||
|
||||
m->userdata = u = pa_xnew(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
u->client = NULL;
|
||||
u->connection = NULL;
|
||||
u->x11 = NULL;
|
||||
u->x11_wrapper = NULL;
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments");
|
||||
|
|
@ -147,9 +198,11 @@ int pa__init(pa_module*m) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!(u->x11 = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
|
||||
if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
|
||||
goto fail;
|
||||
|
||||
u->x11_client = pa_x11_client_new(u->x11_wrapper, NULL, x11_kill_cb, u);
|
||||
|
||||
e = pa_modargs_get_value(ma, "session_manager", NULL);
|
||||
|
||||
if (!e && !getenv("SESSION_MANAGER")) {
|
||||
|
|
@ -253,8 +306,11 @@ void pa__done(pa_module*m) {
|
|||
if (u->client)
|
||||
pa_client_free(u->client);
|
||||
|
||||
if (u->x11)
|
||||
pa_x11_wrapper_unref(u->x11);
|
||||
if (u->x11_client)
|
||||
pa_x11_client_free(u->x11_client);
|
||||
|
||||
if (u->x11_wrapper)
|
||||
pa_x11_wrapper_unref(u->x11_wrapper);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue