xwayland: Fork the X server ourselves
gspawn just isn't us the fine-grained control we need for starting processes and leaking file descriptors in.
This commit is contained in:
parent
c540ddf59b
commit
5cf0740b4e
@ -251,18 +251,6 @@ bind_to_unix_socket (int display)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
uncloexec (gpointer user_data)
|
|
||||||
{
|
|
||||||
int fd = GPOINTER_TO_INT (user_data);
|
|
||||||
|
|
||||||
/* Make sure the client end of the socket pair doesn't get closed
|
|
||||||
* when we exec xwayland. */
|
|
||||||
int flags = fcntl (fd, F_GETFD);
|
|
||||||
if (flags != -1)
|
|
||||||
fcntl (fd, F_SETFD, flags & ~FD_CLOEXEC);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xserver_died (GPid pid,
|
xserver_died (GPid pid,
|
||||||
gint status,
|
gint status,
|
||||||
@ -341,9 +329,8 @@ meta_xwayland_start (MetaXWaylandManager *manager,
|
|||||||
struct wl_display *wl_display)
|
struct wl_display *wl_display)
|
||||||
{
|
{
|
||||||
int sp[2];
|
int sp[2];
|
||||||
pid_t pid;
|
int fd;
|
||||||
char **env;
|
char *socket_fd;
|
||||||
char *fd_string;
|
|
||||||
|
|
||||||
if (!choose_xdisplay (manager))
|
if (!choose_xdisplay (manager))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -361,55 +348,41 @@ meta_xwayland_start (MetaXWaylandManager *manager,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
env = g_get_environ ();
|
manager->pid = fork ();
|
||||||
fd_string = g_strdup_printf ("%d", sp[1]);
|
if (manager->pid == 0)
|
||||||
env = g_environ_setenv (env, "WAYLAND_SOCKET", fd_string, TRUE);
|
{
|
||||||
g_free (fd_string);
|
/* We passed SOCK_CLOEXEC, so dup the FD so it isn't
|
||||||
|
* closed on exec.. */
|
||||||
|
fd = dup (sp[1]);
|
||||||
|
socket_fd = g_strdup_printf ("%d", fd);
|
||||||
|
setenv ("WAYLAND_SOCKET", socket_fd, TRUE);
|
||||||
|
g_free (socket_fd);
|
||||||
|
|
||||||
{
|
/* xwayland, please. */
|
||||||
GError *error = NULL;
|
if (g_getenv ("XWAYLAND_STFU"))
|
||||||
gchar *args[] = { XWAYLAND_PATH,
|
{
|
||||||
manager->display_name,
|
int dev_null;
|
||||||
"-wayland",
|
dev_null = open ("/dev/null", O_WRONLY);
|
||||||
"-rootless",
|
|
||||||
"-noreset",
|
|
||||||
"-nolisten",
|
|
||||||
"all",
|
|
||||||
NULL };
|
|
||||||
int flags = 0;
|
|
||||||
|
|
||||||
flags |= G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
|
dup2 (dev_null, STDOUT_FILENO);
|
||||||
flags |= G_SPAWN_DO_NOT_REAP_CHILD;
|
dup2 (dev_null, STDERR_FILENO);
|
||||||
|
}
|
||||||
|
|
||||||
/* xwayland, please. */
|
if (execl (XWAYLAND_PATH, XWAYLAND_PATH,
|
||||||
if (getenv ("XWAYLAND_STFU"))
|
manager->display_name,
|
||||||
{
|
"-wayland",
|
||||||
flags |= G_SPAWN_STDOUT_TO_DEV_NULL;
|
"-rootless",
|
||||||
flags |= G_SPAWN_STDERR_TO_DEV_NULL;
|
"-noreset",
|
||||||
}
|
"-nolisten", "all",
|
||||||
|
NULL) < 0)
|
||||||
|
{
|
||||||
|
g_warning ("Failed to spawn XWayland: %m");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (g_spawn_async (NULL, /* cwd */
|
g_child_watch_add (manager->pid, xserver_died, NULL);
|
||||||
args,
|
manager->client = wl_client_create (wl_display, sp[0]);
|
||||||
env,
|
|
||||||
flags,
|
|
||||||
uncloexec,
|
|
||||||
GINT_TO_POINTER (sp[1]),
|
|
||||||
&pid,
|
|
||||||
&error))
|
|
||||||
{
|
|
||||||
close (sp[1]);
|
|
||||||
manager->client = wl_client_create (wl_display, sp[0]);
|
|
||||||
|
|
||||||
manager->pid = pid;
|
|
||||||
g_child_watch_add (pid, xserver_died, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_error ("Failed to fork for xwayland server: %s", error->message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_strfreev (env);
|
|
||||||
|
|
||||||
/* We need to run a mainloop until we know xwayland has a binding
|
/* We need to run a mainloop until we know xwayland has a binding
|
||||||
* for our xserver interface at which point we can assume it's
|
* for our xserver interface at which point we can assume it's
|
||||||
|
Loading…
Reference in New Issue
Block a user