mirror of
https://github.com/cage-kiosk/cage.git
synced 2026-03-01 01:40:36 -05:00
cage: switch SIGCHLD handling for pipe
As explained in [1] and [2], SIGCHLD is a tricky signal to handle. A pipe can be used to signal completion instead. [1]: https://github.com/swaywm/wlroots/issues/2012#issuecomment-578908333 [2]: https://stackoverflow.com/questions/8976004/using-waitpid-or-sigaction/8976461#8976461
This commit is contained in:
parent
6be4306b4d
commit
009cca3fa9
1 changed files with 36 additions and 6 deletions
42
cage.c
42
cage.c
|
|
@ -49,14 +49,40 @@
|
||||||
#include "xwayland.h"
|
#include "xwayland.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool
|
static int
|
||||||
spawn_primary_client(char *argv[], pid_t *pid_out)
|
sigchld_handler(int fd, uint32_t mask, void *data)
|
||||||
{
|
{
|
||||||
|
struct wl_display *display = data;
|
||||||
|
|
||||||
|
/* Close Cage's read pipe. */
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (mask & WL_EVENT_HANGUP) {
|
||||||
|
wlr_log(WLR_DEBUG, "Child process closed normally");
|
||||||
|
} else if (mask & WL_EVENT_ERROR) {
|
||||||
|
wlr_log(WLR_DEBUG, "Connection closed by server");
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_display_terminate(display);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
spawn_primary_client(struct wl_display *display, char *argv[], pid_t *pid_out, struct wl_event_source **sigchld_source)
|
||||||
|
{
|
||||||
|
int fd[2];
|
||||||
|
if (pipe(fd) != 0) {
|
||||||
|
wlr_log(WLR_ERROR, "Unable to create pipe");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
sigemptyset(&set);
|
sigemptyset(&set);
|
||||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||||
|
/* Close read, we only need write in the primary client process. */
|
||||||
|
close(fd[0]);
|
||||||
execvp(argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
_exit(1);
|
_exit(1);
|
||||||
} else if (pid == -1) {
|
} else if (pid == -1) {
|
||||||
|
|
@ -64,6 +90,13 @@ spawn_primary_client(char *argv[], pid_t *pid_out)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Close write, we only need read in Cage. */
|
||||||
|
close(fd[1]);
|
||||||
|
|
||||||
|
struct wl_event_loop *event_loop = wl_display_get_event_loop(display);
|
||||||
|
uint32_t mask = WL_EVENT_HANGUP | WL_EVENT_ERROR;
|
||||||
|
*sigchld_source = wl_event_loop_add_fd(event_loop, fd[0], mask, sigchld_handler, display);
|
||||||
|
|
||||||
*pid_out = pid;
|
*pid_out = pid;
|
||||||
wlr_log(WLR_DEBUG, "Child process created with pid %d", pid);
|
wlr_log(WLR_DEBUG, "Child process created with pid %d", pid);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -111,8 +144,6 @@ handle_signal(int signal, void *data)
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
/* Fallthrough */
|
/* Fallthrough */
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
/* Fallthrough */
|
|
||||||
case SIGCHLD:
|
|
||||||
wl_display_terminate(display);
|
wl_display_terminate(display);
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
|
|
@ -230,7 +261,6 @@ main(int argc, char *argv[])
|
||||||
event_loop = wl_display_get_event_loop(server.wl_display);
|
event_loop = wl_display_get_event_loop(server.wl_display);
|
||||||
sigint_source = wl_event_loop_add_signal(event_loop, SIGINT, handle_signal, &server.wl_display);
|
sigint_source = wl_event_loop_add_signal(event_loop, SIGINT, handle_signal, &server.wl_display);
|
||||||
sigterm_source = wl_event_loop_add_signal(event_loop, SIGTERM, handle_signal, &server.wl_display);
|
sigterm_source = wl_event_loop_add_signal(event_loop, SIGTERM, handle_signal, &server.wl_display);
|
||||||
sigchld_source = wl_event_loop_add_signal(event_loop, SIGCHLD, handle_signal, &server.wl_display);
|
|
||||||
|
|
||||||
server.backend = wlr_backend_autocreate(server.wl_display, NULL);
|
server.backend = wlr_backend_autocreate(server.wl_display, NULL);
|
||||||
if (!server.backend) {
|
if (!server.backend) {
|
||||||
|
|
@ -420,7 +450,7 @@ main(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
if (!spawn_primary_client(argv + optind, &pid)) {
|
if (!spawn_primary_client(server.wl_display, argv + optind, &pid, &sigchld_source)) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue