Merge pull request #1562 from emersion/remove-sock-cloexec

xwayland: don't use SOCK_CLOEXEC
This commit is contained in:
Drew DeVault 2019-02-19 10:45:57 -05:00 committed by GitHub
commit dcd05f67ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 50 additions and 33 deletions

View File

@ -1,8 +1,4 @@
#define _POSIX_C_SOURCE 200112L #define _POSIX_C_SOURCE 200112L
#ifdef __FreeBSD__
// for SOCK_CLOEXEC
#define __BSD_VISIBLE 1
#endif
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <signal.h> #include <signal.h>
@ -36,12 +32,22 @@ static void safe_close(int fd) {
} }
} }
static int unset_cloexec(int fd) { static bool set_cloexec(int fd, bool cloexec) {
if (fcntl(fd, F_SETFD, 0) != 0) { int flags = fcntl(fd, F_GETFD);
wlr_log_errno(WLR_ERROR, "fcntl() failed on fd %d", fd); if (flags == -1) {
return -1; wlr_log_errno(WLR_ERROR, "fcntl failed");
return false;
} }
return 0; if (cloexec) {
flags = flags | FD_CLOEXEC;
} else {
flags = flags & ~FD_CLOEXEC;
}
if (fcntl(fd, F_SETFD, flags) == -1) {
wlr_log_errno(WLR_ERROR, "fcntl failed");
return false;
}
return true;
} }
static int fill_arg(char ***argv, const char *fmt, ...) { static int fill_arg(char ***argv, const char *fmt, ...) {
@ -65,12 +71,11 @@ static int fill_arg(char ***argv, const char *fmt, ...) {
return len; return len;
} }
_Noreturn _Noreturn static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) {
static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) { if (!set_cloexec(wlr_xwayland->x_fd[0], false) ||
if (unset_cloexec(wlr_xwayland->x_fd[0]) || !set_cloexec(wlr_xwayland->x_fd[1], false) ||
unset_cloexec(wlr_xwayland->x_fd[1]) || !set_cloexec(wlr_xwayland->wm_fd[1], false) ||
unset_cloexec(wlr_xwayland->wm_fd[1]) || !set_cloexec(wlr_xwayland->wl_fd[1], false)) {
unset_cloexec(wlr_xwayland->wl_fd[1])) {
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
@ -83,7 +88,8 @@ static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) {
"-listen", NULL /* x_fd[0] */, "-listen", NULL /* x_fd[0] */,
"-listen", NULL /* x_fd[1] */, "-listen", NULL /* x_fd[1] */,
"-wm", NULL /* wm_fd[1] */, "-wm", NULL /* wm_fd[1] */,
NULL }; NULL,
};
char **cur_arg = argv; char **cur_arg = argv;
if (fill_arg(&cur_arg, ":%d", wlr_xwayland->display) < 0 || if (fill_arg(&cur_arg, ":%d", wlr_xwayland->display) < 0 ||
@ -304,16 +310,25 @@ static bool xwayland_start_display(struct wlr_xwayland *wlr_xwayland,
} }
static bool xwayland_start_server(struct wlr_xwayland *wlr_xwayland) { static bool xwayland_start_server(struct wlr_xwayland *wlr_xwayland) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, wlr_xwayland->wl_fd) != 0 ||
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wlr_xwayland->wl_fd) != 0 || socketpair(AF_UNIX, SOCK_STREAM, 0, wlr_xwayland->wm_fd) != 0) {
socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wlr_xwayland->wm_fd) != 0) { wlr_log_errno(WLR_ERROR, "socketpair failed");
wlr_log_errno(WLR_ERROR, "failed to create socketpair");
xwayland_finish_server(wlr_xwayland); xwayland_finish_server(wlr_xwayland);
return false; return false;
} }
if (!set_cloexec(wlr_xwayland->wl_fd[0], true) ||
!set_cloexec(wlr_xwayland->wl_fd[1], true) ||
!set_cloexec(wlr_xwayland->wm_fd[0], true) ||
!set_cloexec(wlr_xwayland->wm_fd[1], true)) {
xwayland_finish_server(wlr_xwayland);
return false;
}
wlr_xwayland->server_start = time(NULL); wlr_xwayland->server_start = time(NULL);
if (!(wlr_xwayland->client = wl_client_create(wlr_xwayland->wl_display, wlr_xwayland->wl_fd[0]))) { wlr_xwayland->client =
wl_client_create(wlr_xwayland->wl_display, wlr_xwayland->wl_fd[0]);
if (!wlr_xwayland->client) {
wlr_log_errno(WLR_ERROR, "wl_client_create failed"); wlr_log_errno(WLR_ERROR, "wl_client_create failed");
xwayland_finish_server(wlr_xwayland); xwayland_finish_server(wlr_xwayland);
return false; return false;
@ -329,24 +344,30 @@ static bool xwayland_start_server(struct wlr_xwayland *wlr_xwayland) {
wlr_xwayland->sigusr1_source = wl_event_loop_add_signal(loop, SIGUSR1, wlr_xwayland->sigusr1_source = wl_event_loop_add_signal(loop, SIGUSR1,
xserver_handle_ready, wlr_xwayland); xserver_handle_ready, wlr_xwayland);
if ((wlr_xwayland->pid = fork()) == 0) { wlr_xwayland->pid = fork();
if (wlr_xwayland->pid < 0) {
wlr_log_errno(WLR_ERROR, "fork failed");
xwayland_finish_server(wlr_xwayland);
return false;
} else if (wlr_xwayland->pid == 0) {
/* Double-fork, but we need to forward SIGUSR1 once Xserver(1) /* Double-fork, but we need to forward SIGUSR1 once Xserver(1)
* is ready, or error if there was one. */ * is ready, or error if there was one. */
pid_t pid, ppid; pid_t ppid = getppid();
sigset_t sigset; sigset_t sigset;
int sig;
ppid = getppid();
sigemptyset(&sigset); sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1); sigaddset(&sigset, SIGUSR1);
sigaddset(&sigset, SIGCHLD); sigaddset(&sigset, SIGCHLD);
sigprocmask(SIG_BLOCK, &sigset, NULL); sigprocmask(SIG_BLOCK, &sigset, NULL);
if ((pid = fork()) == 0) {
exec_xwayland(wlr_xwayland); pid_t pid = fork();
}
if (pid < 0) { if (pid < 0) {
wlr_log_errno(WLR_ERROR, "second fork failed"); wlr_log_errno(WLR_ERROR, "second fork failed");
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} else if (pid == 0) {
exec_xwayland(wlr_xwayland);
} }
int sig;
sigwait(&sigset, &sig); sigwait(&sigset, &sig);
kill(ppid, SIGUSR1); kill(ppid, SIGUSR1);
wlr_log(WLR_DEBUG, "sent SIGUSR1 to process %d", ppid); wlr_log(WLR_DEBUG, "sent SIGUSR1 to process %d", ppid);
@ -354,13 +375,9 @@ static bool xwayland_start_server(struct wlr_xwayland *wlr_xwayland) {
waitpid(pid, NULL, 0); waitpid(pid, NULL, 0);
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
_exit(EXIT_SUCCESS); _exit(EXIT_SUCCESS);
} }
if (wlr_xwayland->pid < 0) {
wlr_log_errno(WLR_ERROR, "fork failed");
xwayland_finish_server(wlr_xwayland);
return false;
}
/* close child fds */ /* close child fds */
/* remain managing x sockets for lazy start */ /* remain managing x sockets for lazy start */