mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-24 19:22:11 +01:00
GSubprocessLauncher: Move cleanup to dispose()
The GSubprocessLauncher class lacks a dispose() method, and frees all their resources in the finalize() method. This is a problem with Javascript because the sockets passed to a child process using g_subprocess_launcher_take_fd() aren't closed in the parent space until the object is fully freed. This means that if the child closes a socket, it won't be detected until the GSubprocessLauncher object has been freed by the garbage collector. Just closing the socket externally is not a valid solution, because the finalize() method will close it again, and since another file/pipe/socket could have been opened in the meantime and use the same FD number, the finalize() method would close an incorrect FD. An example is launching a child process that uses its own socket for Wayland: the parent creates two sockets with socketpair(), passes one to the Wayland API (wl_client_create()), and the other is passed to the child process using g_subprocess_launcher_take_fd(). But now there are two instances of that second socket: one in the parent, and another one in the child process. That means that, if the child closes its socket (or dies), the Wayland server will not detect that until the GSubprocessLauncher object is fully destroyed. That means that a GSubprocessLauncher created in Javascript will last for several seconds after the child dies, and every window or graphical element will remain in the screen until the Garbage Collector destroys the GSubprocessLauncher object. This patch fixes this by moving the resource free code into a dispose() method, which can be called from Javascript. This allows to ensure that any socket passed to the child with g_subprocess_launcher_take_fd() can be closed even from Javascript just by calling the method run_dispose(). Fix https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1670
This commit is contained in:
parent
f01ca92821
commit
605cff61da
@ -131,47 +131,52 @@ g_subprocess_launcher_set_property (GObject *object, guint prop_id,
|
||||
}
|
||||
|
||||
static void
|
||||
g_subprocess_launcher_finalize (GObject *object)
|
||||
g_subprocess_launcher_dispose (GObject *object)
|
||||
{
|
||||
GSubprocessLauncher *self = G_SUBPROCESS_LAUNCHER (object);
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
guint i;
|
||||
|
||||
g_free (self->stdin_path);
|
||||
g_free (self->stdout_path);
|
||||
g_free (self->stderr_path);
|
||||
g_clear_pointer (&self->stdin_path, g_free);
|
||||
g_clear_pointer (&self->stdout_path, g_free);
|
||||
g_clear_pointer (&self->stderr_path, g_free);
|
||||
|
||||
if (self->stdin_fd != -1)
|
||||
close (self->stdin_fd);
|
||||
self->stdin_fd = -1;
|
||||
|
||||
if (self->stdout_fd != -1)
|
||||
close (self->stdout_fd);
|
||||
self->stdout_fd = -1;
|
||||
|
||||
if (self->stderr_fd != -1)
|
||||
close (self->stderr_fd);
|
||||
self->stderr_fd = -1;
|
||||
|
||||
if (self->basic_fd_assignments)
|
||||
{
|
||||
for (i = 0; i < self->basic_fd_assignments->len; i++)
|
||||
(void) close (g_array_index (self->basic_fd_assignments, int, i));
|
||||
g_array_unref (self->basic_fd_assignments);
|
||||
g_clear_pointer (&self->basic_fd_assignments, g_array_unref);
|
||||
}
|
||||
if (self->needdup_fd_assignments)
|
||||
{
|
||||
for (i = 0; i < self->needdup_fd_assignments->len; i += 2)
|
||||
(void) close (g_array_index (self->needdup_fd_assignments, int, i));
|
||||
g_array_unref (self->needdup_fd_assignments);
|
||||
g_clear_pointer (&self->needdup_fd_assignments, g_array_unref);
|
||||
}
|
||||
|
||||
if (self->child_setup_destroy_notify)
|
||||
(* self->child_setup_destroy_notify) (self->child_setup_user_data);
|
||||
self->child_setup_destroy_notify = NULL;
|
||||
self->child_setup_user_data = NULL;
|
||||
#endif
|
||||
|
||||
g_strfreev (self->envp);
|
||||
g_free (self->cwd);
|
||||
g_clear_pointer (&self->envp, g_strfreev);
|
||||
g_clear_pointer (&self->cwd, g_free);
|
||||
|
||||
G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -194,7 +199,7 @@ g_subprocess_launcher_class_init (GSubprocessLauncherClass *class)
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->set_property = g_subprocess_launcher_set_property;
|
||||
gobject_class->finalize = g_subprocess_launcher_finalize;
|
||||
gobject_class->dispose = g_subprocess_launcher_dispose;
|
||||
|
||||
g_object_class_install_property (gobject_class, 1,
|
||||
g_param_spec_flags ("flags", "Flags", "GSubprocessFlags for launched processes",
|
||||
@ -634,12 +639,16 @@ g_subprocess_launcher_take_fd (GSubprocessLauncher *self,
|
||||
{
|
||||
if (source_fd == target_fd)
|
||||
{
|
||||
g_array_append_val (self->basic_fd_assignments, source_fd);
|
||||
if (self->basic_fd_assignments)
|
||||
g_array_append_val (self->basic_fd_assignments, source_fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_array_append_val (self->needdup_fd_assignments, source_fd);
|
||||
g_array_append_val (self->needdup_fd_assignments, target_fd);
|
||||
if (self->needdup_fd_assignments)
|
||||
{
|
||||
g_array_append_val (self->needdup_fd_assignments, source_fd);
|
||||
g_array_append_val (self->needdup_fd_assignments, target_fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user