mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2025-12-25 10:40:12 +01:00
xwayland: Reuse weston_client_launch
Now that our process-launching internals are identical between the
(still-misnamed) weston_client_launch and the frontend's Xwayland
launcher, we can reuse the internals instead of open-coding it.
As a result, we now additionally prevent Xwayland from inheriting
Weston's signal mask, by clearing SIG_UNBLOCK on all signals. This
should have no observable effect as we do not depend on signal handling
within Xwayland, instead using the displayfd readiness mechanism since
c2f4201ed2.
Signed-off-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
parent
dfda0ca9d2
commit
3ac2748021
1 changed files with 47 additions and 82 deletions
|
|
@ -91,11 +91,20 @@ out:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xserver_cleanup(struct weston_process *process, int status)
|
||||||
|
{
|
||||||
|
struct wet_xwayland *wxw =
|
||||||
|
container_of(process, struct wet_xwayland, process);
|
||||||
|
|
||||||
|
wxw->api->xserver_exited(wxw->xwayland, status);
|
||||||
|
wxw->client = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static pid_t
|
static pid_t
|
||||||
spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd)
|
spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd)
|
||||||
{
|
{
|
||||||
struct wet_xwayland *wxw = user_data;
|
struct wet_xwayland *wxw = user_data;
|
||||||
pid_t pid;
|
|
||||||
struct fdstr wayland_socket = FDSTR_INIT;
|
struct fdstr wayland_socket = FDSTR_INIT;
|
||||||
struct fdstr x11_abstract_socket = FDSTR_INIT;
|
struct fdstr x11_abstract_socket = FDSTR_INIT;
|
||||||
struct fdstr x11_unix_socket = FDSTR_INIT;
|
struct fdstr x11_unix_socket = FDSTR_INIT;
|
||||||
|
|
@ -105,34 +114,29 @@ spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd
|
||||||
struct weston_config *config = wet_get_config(wxw->compositor);
|
struct weston_config *config = wet_get_config(wxw->compositor);
|
||||||
struct weston_config_section *section;
|
struct weston_config_section *section;
|
||||||
struct wl_event_loop *loop;
|
struct wl_event_loop *loop;
|
||||||
char *exec_failure_msg;
|
|
||||||
const char *cloexec_failure_msg = "Couldn't unset CLOEXEC on child FDs";
|
|
||||||
struct custom_env child_env;
|
struct custom_env child_env;
|
||||||
int no_cloexec_fds[5];
|
int no_cloexec_fds[5];
|
||||||
size_t num_no_cloexec_fds = 0;
|
size_t num_no_cloexec_fds = 0;
|
||||||
size_t i;
|
|
||||||
char *const *envp;
|
|
||||||
char *const *argp;
|
|
||||||
int ret;
|
int ret;
|
||||||
size_t written __attribute__ ((unused));
|
size_t written __attribute__ ((unused));
|
||||||
|
|
||||||
if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, wayland_socket.fds) < 0) {
|
if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, wayland_socket.fds) < 0) {
|
||||||
weston_log("wl connection socketpair failed\n");
|
weston_log("wl connection socketpair failed\n");
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
fdstr_update_str1(&wayland_socket);
|
fdstr_update_str1(&wayland_socket);
|
||||||
no_cloexec_fds[num_no_cloexec_fds++] = wayland_socket.fds[1];
|
no_cloexec_fds[num_no_cloexec_fds++] = wayland_socket.fds[1];
|
||||||
|
|
||||||
if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, x11_wm_socket.fds) < 0) {
|
if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, x11_wm_socket.fds) < 0) {
|
||||||
weston_log("X wm connection socketpair failed\n");
|
weston_log("X wm connection socketpair failed\n");
|
||||||
goto err_wayland_socket;
|
goto err;
|
||||||
}
|
}
|
||||||
fdstr_update_str1(&x11_wm_socket);
|
fdstr_update_str1(&x11_wm_socket);
|
||||||
no_cloexec_fds[num_no_cloexec_fds++] = x11_wm_socket.fds[1];
|
no_cloexec_fds[num_no_cloexec_fds++] = x11_wm_socket.fds[1];
|
||||||
|
|
||||||
if (pipe2(display_pipe.fds, O_CLOEXEC) < 0) {
|
if (pipe2(display_pipe.fds, O_CLOEXEC) < 0) {
|
||||||
weston_log("pipe creation for displayfd failed\n");
|
weston_log("pipe creation for displayfd failed\n");
|
||||||
goto err_x11_wm_socket;
|
goto err;
|
||||||
}
|
}
|
||||||
fdstr_update_str1(&display_pipe);
|
fdstr_update_str1(&display_pipe);
|
||||||
no_cloexec_fds[num_no_cloexec_fds++] = display_pipe.fds[1];
|
no_cloexec_fds[num_no_cloexec_fds++] = display_pipe.fds[1];
|
||||||
|
|
@ -148,8 +152,6 @@ spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd
|
||||||
section = weston_config_get_section(config, "xwayland", NULL, NULL);
|
section = weston_config_get_section(config, "xwayland", NULL, NULL);
|
||||||
weston_config_section_get_string(section, "path",
|
weston_config_section_get_string(section, "path",
|
||||||
&xserver, XSERVER_PATH);
|
&xserver, XSERVER_PATH);
|
||||||
str_printf(&exec_failure_msg,
|
|
||||||
"Error: executing Xwayland as '%s' failed.\n", xserver);
|
|
||||||
custom_env_init_from_environ(&child_env);
|
custom_env_init_from_environ(&child_env);
|
||||||
custom_env_set_env_var(&child_env, "WAYLAND_SOCKET", wayland_socket.str1);
|
custom_env_set_env_var(&child_env, "WAYLAND_SOCKET", wayland_socket.str1);
|
||||||
|
|
||||||
|
|
@ -166,87 +168,50 @@ spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd
|
||||||
custom_env_add_arg(&child_env, x11_wm_socket.str1);
|
custom_env_add_arg(&child_env, x11_wm_socket.str1);
|
||||||
custom_env_add_arg(&child_env, "-terminate");
|
custom_env_add_arg(&child_env, "-terminate");
|
||||||
|
|
||||||
envp = custom_env_get_envp(&child_env);
|
ret = weston_client_launch(wxw->compositor, &wxw->process, &child_env,
|
||||||
argp = custom_env_get_argp(&child_env);
|
no_cloexec_fds, num_no_cloexec_fds,
|
||||||
|
xserver_cleanup);
|
||||||
pid = fork();
|
if (!ret) {
|
||||||
switch (pid) {
|
weston_log("Couldn't start Xwayland\n");
|
||||||
case 0:
|
goto err;
|
||||||
setsid();
|
|
||||||
|
|
||||||
for (i = 0; i < num_no_cloexec_fds; i++) {
|
|
||||||
ret = os_fd_clear_cloexec(no_cloexec_fds[i]);
|
|
||||||
if (ret < 0) {
|
|
||||||
write(STDERR_FILENO, cloexec_failure_msg,
|
|
||||||
strlen(cloexec_failure_msg));
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
execve(xserver, argp, envp);
|
|
||||||
/* execve does not return on success, so it failed */
|
|
||||||
|
|
||||||
if (exec_failure_msg) {
|
|
||||||
written = write(STDERR_FILENO, exec_failure_msg,
|
|
||||||
strlen(exec_failure_msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
default:
|
|
||||||
close(wayland_socket.fds[1]);
|
|
||||||
wxw->client = wl_client_create(wxw->compositor->wl_display,
|
|
||||||
wayland_socket.fds[0]);
|
|
||||||
|
|
||||||
close(x11_wm_socket.fds[1]);
|
|
||||||
wxw->wm_fd = x11_wm_socket.fds[0];
|
|
||||||
|
|
||||||
/* During initialization the X server will round trip
|
|
||||||
* and block on the wayland compositor, so avoid making
|
|
||||||
* blocking requests (like xcb_connect_to_fd) until
|
|
||||||
* it's done with that. */
|
|
||||||
close(display_pipe.fds[1]);
|
|
||||||
loop = wl_display_get_event_loop(wxw->compositor->wl_display);
|
|
||||||
wxw->display_fd_source =
|
|
||||||
wl_event_loop_add_fd(loop, display_pipe.fds[0],
|
|
||||||
WL_EVENT_READABLE,
|
|
||||||
handle_display_fd, wxw);
|
|
||||||
|
|
||||||
wxw->process.pid = pid;
|
|
||||||
wet_watch_process(wxw->compositor, &wxw->process);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case -1:
|
|
||||||
weston_log("Failed to fork to spawn xserver process\n");
|
|
||||||
fdstr_close_all(&wayland_socket);
|
|
||||||
fdstr_close_all(&x11_wm_socket);
|
|
||||||
fdstr_close_all(&display_pipe);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
custom_env_fini(&child_env);
|
wxw->client = wl_client_create(wxw->compositor->wl_display,
|
||||||
free(exec_failure_msg);
|
wayland_socket.fds[0]);
|
||||||
|
if (!wxw->client) {
|
||||||
|
weston_log("Couldn't create client for Xwayland\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxw->wm_fd = x11_wm_socket.fds[0];
|
||||||
|
|
||||||
|
/* Now we can no longer fail, close the child end of our sockets */
|
||||||
|
close(wayland_socket.fds[1]);
|
||||||
|
close(x11_wm_socket.fds[1]);
|
||||||
|
close(display_pipe.fds[1]);
|
||||||
|
|
||||||
|
/* During initialization the X server will round trip
|
||||||
|
* and block on the wayland compositor, so avoid making
|
||||||
|
* blocking requests (like xcb_connect_to_fd) until
|
||||||
|
* it's done with that. */
|
||||||
|
loop = wl_display_get_event_loop(wxw->compositor->wl_display);
|
||||||
|
wxw->display_fd_source =
|
||||||
|
wl_event_loop_add_fd(loop, display_pipe.fds[0],
|
||||||
|
WL_EVENT_READABLE,
|
||||||
|
handle_display_fd, wxw);
|
||||||
|
|
||||||
free(xserver);
|
free(xserver);
|
||||||
|
|
||||||
return pid;
|
return wxw->process.pid;
|
||||||
|
|
||||||
err_x11_wm_socket:
|
err:
|
||||||
|
free(xserver);
|
||||||
|
fdstr_close_all(&display_pipe);
|
||||||
fdstr_close_all(&x11_wm_socket);
|
fdstr_close_all(&x11_wm_socket);
|
||||||
err_wayland_socket:
|
|
||||||
fdstr_close_all(&wayland_socket);
|
fdstr_close_all(&wayland_socket);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
xserver_cleanup(struct weston_process *process, int status)
|
|
||||||
{
|
|
||||||
struct wet_xwayland *wxw =
|
|
||||||
container_of(process, struct wet_xwayland, process);
|
|
||||||
|
|
||||||
wxw->api->xserver_exited(wxw->xwayland, status);
|
|
||||||
wxw->client = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wxw_compositor_destroy(struct wl_listener *listener, void *data)
|
wxw_compositor_destroy(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue