mirror of
https://github.com/labwc/labwc.git
synced 2025-11-04 13:30:07 -05:00
spawn: avoid zombie children without handling SIGCHLD
Current handling of SIGCHLD prevents some terminals, for example sakura and alacritty, to freeze on ctrl+D. Related to PR #10
This commit is contained in:
parent
f4cbd4ff61
commit
1a38898f34
2 changed files with 43 additions and 25 deletions
|
|
@ -1,4 +1,14 @@
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#include <assert.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "common/log.h"
|
||||||
|
#include "common/spawn.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
spawn_async_no_shell(char const *command)
|
spawn_async_no_shell(char const *command)
|
||||||
|
|
@ -6,18 +16,45 @@ spawn_async_no_shell(char const *command)
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
gchar **argv = NULL;
|
gchar **argv = NULL;
|
||||||
|
|
||||||
|
assert(command);
|
||||||
|
|
||||||
|
/* Use glib's shell-parse to mimic Openbox's behaviour */
|
||||||
g_shell_parse_argv((gchar *)command, NULL, &argv, &err);
|
g_shell_parse_argv((gchar *)command, NULL, &argv, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
g_message("%s", err->message);
|
g_message("%s", err->message);
|
||||||
g_error_free(err);
|
g_error_free(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_spawn_async(NULL, argv, NULL,
|
|
||||||
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
|
/*
|
||||||
NULL, &err);
|
* Avoid zombie processes by using a double-fork, whereby the
|
||||||
if (err) {
|
* grandchild becomes orphaned & the responsibility of the OS.
|
||||||
g_message("%s", err->message);
|
*/
|
||||||
g_error_free(err);
|
pid_t child = 0, grandchild = 0;
|
||||||
|
|
||||||
|
child = fork();
|
||||||
|
switch (child) {
|
||||||
|
case -1:
|
||||||
|
warn("unable to fork()");
|
||||||
|
goto out;
|
||||||
|
case 0:
|
||||||
|
setsid();
|
||||||
|
sigset_t set;
|
||||||
|
sigemptyset(&set);
|
||||||
|
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||||
|
grandchild = fork();
|
||||||
|
if (grandchild == 0) {
|
||||||
|
execvp(argv[0], argv);
|
||||||
|
exit(0);
|
||||||
|
} else if (grandchild < 0) {
|
||||||
|
warn("unable to fork()");
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
waitpid(child, NULL, 0);
|
||||||
|
out:
|
||||||
g_strfreev(argv);
|
g_strfreev(argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
19
src/server.c
19
src/server.c
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
static struct wlr_compositor *compositor;
|
static struct wlr_compositor *compositor;
|
||||||
static struct wl_event_source *sighup_source;
|
static struct wl_event_source *sighup_source;
|
||||||
static struct wl_event_source *sigchld_source;
|
|
||||||
static struct wl_event_source *sigint_source;
|
static struct wl_event_source *sigint_source;
|
||||||
static struct wl_event_source *sigterm_source;
|
static struct wl_event_source *sigterm_source;
|
||||||
|
|
||||||
|
|
@ -34,19 +33,6 @@ handle_sighup(int signal, void *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
handle_sigchld(int signal, void *data)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0);
|
|
||||||
if (pid < 0) {
|
|
||||||
wlr_log_errno(WLR_ERROR, "waitpid");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
handle_sigterm(int signal, void *data)
|
handle_sigterm(int signal, void *data)
|
||||||
{
|
{
|
||||||
|
|
@ -86,8 +72,6 @@ server_init(struct server *server)
|
||||||
event_loop = wl_display_get_event_loop(server->wl_display);
|
event_loop = wl_display_get_event_loop(server->wl_display);
|
||||||
sighup_source = wl_event_loop_add_signal(
|
sighup_source = wl_event_loop_add_signal(
|
||||||
event_loop, SIGHUP, handle_sighup, &server->wl_display);
|
event_loop, SIGHUP, handle_sighup, &server->wl_display);
|
||||||
sigchld_source = wl_event_loop_add_signal(
|
|
||||||
event_loop, SIGCHLD, handle_sigchld, NULL);
|
|
||||||
sigint_source = wl_event_loop_add_signal(
|
sigint_source = wl_event_loop_add_signal(
|
||||||
event_loop, SIGINT, handle_sigterm, NULL);
|
event_loop, SIGINT, handle_sigterm, NULL);
|
||||||
sigterm_source = wl_event_loop_add_signal(
|
sigterm_source = wl_event_loop_add_signal(
|
||||||
|
|
@ -263,9 +247,6 @@ server_finish(struct server *server)
|
||||||
if (sighup_source) {
|
if (sighup_source) {
|
||||||
wl_event_source_remove(sighup_source);
|
wl_event_source_remove(sighup_source);
|
||||||
}
|
}
|
||||||
if (sigchld_source) {
|
|
||||||
wl_event_source_remove(sigchld_source);
|
|
||||||
}
|
|
||||||
wl_display_destroy_clients(server->wl_display);
|
wl_display_destroy_clients(server->wl_display);
|
||||||
|
|
||||||
seat_finish(server);
|
seat_finish(server);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue