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:
Jasper St. Pierre 2014-04-01 19:51:43 -04:00
parent c540ddf59b
commit 5cf0740b4e

View File

@ -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