From: Igor V. Kovalenko Date: Wed, 23 Dec 2020 07:31:18 +0000 (+0300) Subject: x11: gracefully handle ICE connection error X-Git-Tag: v14.99.1~222 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6bfd9c809e1a679043c6c4bfdd1e117ed7b5fc2a;p=platform%2Fupstream%2Fpulseaudio.git x11: gracefully handle ICE connection error Implementation is largely inspired by GNOME/mutter ICE session handling. Part-of: --- diff --git a/src/modules/x11/module-x11-xsmp.c b/src/modules/x11/module-x11-xsmp.c index eb18b43..1ff6cc7 100644 --- a/src/modules/x11/module-x11-xsmp.c +++ b/src/modules/x11/module-x11-xsmp.c @@ -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); - - pa_x11_wrapper_unref(u->x11); - u->x11 = NULL; + if (u->connection) { + SmcCloseConnection(u->connection, 0, NULL); + u->connection = 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; + + ice_installed_handler = IceSetIOErrorHandler (NULL); + default_handler = IceSetIOErrorHandler (ice_io_error_handler); - IceAddConnectionWatch(new_ice_connection, m->core); - ice_in_use = true; + 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); }