diff --git a/CHANGELOG.md b/CHANGELOG.md index 20e7730b..822b5527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ line is empty. * Number of lines to scroll is now always clamped to the number of lines in the scrolling region.. +* New terminal windows spawned with `ctrl`+`shift`+`n` is no longer + double forked. ### Deprecated diff --git a/main.c b/main.c index b7b051f5..d662cd72 100644 --- a/main.c +++ b/main.c @@ -390,14 +390,14 @@ main(int argc, char *const *argv) goto out; if (!as_server && (term = term_init( - &conf, fdm, wayl, "foot", cwd, argc, argv, + &conf, fdm, reaper, wayl, "foot", cwd, argc, argv, &term_shutdown_cb, &shutdown_ctx)) == NULL) { free(cwd); goto out; } free(cwd); - if (as_server && (server = server_init(&conf, fdm, wayl)) == NULL) + if (as_server && (server = server_init(&conf, fdm, reaper, wayl)) == NULL) goto out; /* Remember to restore signals in slave */ diff --git a/server.c b/server.c index 75990ecd..ab627877 100644 --- a/server.c +++ b/server.c @@ -24,6 +24,7 @@ struct client; struct server { const struct config *conf; struct fdm *fdm; + struct reaper *reaper; struct wayland *wayl; int fd; @@ -311,7 +312,7 @@ fdm_client(struct fdm *fdm, int fd, int events, void *data) client->conf.startup_mode = STARTUP_FULLSCREEN; client->term = term_init( - &client->conf, server->fdm, server->wayl, + &client->conf, server->fdm, server->reaper, server->wayl, "footclient", cwd, argc, argv, &term_shutdown_handler, client); if (client->term == NULL) { @@ -406,7 +407,8 @@ err: } struct server * -server_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl) +server_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, + struct wayland *wayl) { int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); if (fd == -1) { @@ -448,6 +450,7 @@ server_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl) *server = (struct server) { .conf = conf, .fdm = fdm, + .reaper = reaper, .wayl = wayl, .fd = fd, diff --git a/server.h b/server.h index a5f34071..55a031b4 100644 --- a/server.h +++ b/server.h @@ -5,5 +5,6 @@ #include "wayland.h" struct server; -struct server *server_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl); +struct server *server_init(const struct config *conf, struct fdm *fdm, + struct reaper *reaper, struct wayland *wayl); void server_destroy(struct server *server); diff --git a/terminal.c b/terminal.c index 5e17e7c9..4f9d1d5d 100644 --- a/terminal.c +++ b/terminal.c @@ -23,6 +23,7 @@ #include "config.h" #include "grid.h" #include "quirks.h" +#include "reaper.h" #include "render.h" #include "selection.h" #include "sixel.h" @@ -714,8 +715,9 @@ load_fonts_from_conf(const struct terminal *term, const struct config *conf, } struct terminal * -term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, - const char *foot_exe, const char *cwd, int argc, char *const *argv, +term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, + struct wayland *wayl, const char *foot_exe, const char *cwd, + int argc, char *const *argv, void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data) { int ptmx = -1; @@ -784,6 +786,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, /* Initialize configure-based terminal attributes */ *term = (struct terminal) { .fdm = fdm, + .reaper = reaper, .conf = conf, .quit = false, .ptmx = ptmx, @@ -2221,69 +2224,59 @@ term_flash(struct terminal *term, unsigned duration_ms) bool term_spawn_new(const struct terminal *term) { + int pipe_fds[2] = {-1, -1}; + if (pipe2(pipe_fds, O_CLOEXEC) < 0) { + LOG_ERRNO("failed to create pipe"); + goto err; + } + pid_t pid = fork(); if (pid < 0) { LOG_ERRNO("failed to fork new terminal"); - return false; + goto err; } if (pid == 0) { /* Child */ - int pipe_fds[2] = {-1, -1}; - if (pipe2(pipe_fds, O_CLOEXEC) < 0) { - LOG_ERRNO("failed to create pipe"); - goto err; - } - - /* Double fork */ - pid_t pid2 = fork(); - if (pid2 < 0) { - LOG_ERRNO("failed to double fork new terminal"); - goto err; - } - - if (pid2 == 0) { - /* Child */ - close(pipe_fds[0]); - if (chdir(term->cwd) < 0 || - execlp(term->foot_exe, term->foot_exe, NULL) < 0) - { - (void)!write(pipe_fds[1], &errno, sizeof(errno)); - _exit(errno); - } - assert(false); + close(pipe_fds[0]); + if (chdir(term->cwd) < 0 || + execlp(term->foot_exe, term->foot_exe, NULL) < 0) + { + (void)!write(pipe_fds[1], &errno, sizeof(errno)); _exit(errno); } - - /* Parent */ - - close(pipe_fds[1]); - - int _errno; - static_assert(sizeof(_errno) == sizeof(errno), "errno size mismatch"); - - ssize_t ret = read(pipe_fds[0], &_errno, sizeof(_errno)); - close(pipe_fds[0]); - - if (ret == 0) - _exit(0); - else if (ret < 0) - LOG_ERRNO("failed to read from pipe"); - else { - LOG_ERRNO_P("%s: failed to spawn new terminal", _errno, term->foot_exe); - errno = _errno; - waitpid(pid2, NULL, 0); - } - - err: - if (pipe_fds[0] != -1) - close(pipe_fds[0]); + assert(false); _exit(errno); } - int result; - waitpid(pid, &result, 0); - return WIFEXITED(result) && WEXITSTATUS(result) == 0; + /* Parent */ + close(pipe_fds[1]); + + int _errno; + static_assert(sizeof(_errno) == sizeof(errno), "errno size mismatch"); + + ssize_t ret = read(pipe_fds[0], &_errno, sizeof(_errno)); + close(pipe_fds[0]); + + if (ret == 0) { + reaper_add(term->reaper, pid); + return true; + } else if (ret < 0) { + LOG_ERRNO("failed to read from pipe"); + return false; + } else { + LOG_ERRNO_P("%s: failed to spawn new terminal", _errno, term->foot_exe); + errno = _errno; + waitpid(pid, NULL, 0); + return false; + } + +err: + if (pipe_fds[0] != -1) + close(pipe_fds[0]); + if (pipe_fds[1] != -1) + close(pipe_fds[1]); + return false; } void diff --git a/terminal.h b/terminal.h index 395557db..295db8e8 100644 --- a/terminal.h +++ b/terminal.h @@ -13,6 +13,7 @@ //#include "config.h" #include "fdm.h" +#include "reaper.h" #include "wayland.h" #define likely(c) __builtin_expect(!!(c), 1) @@ -206,6 +207,7 @@ enum term_surface { struct terminal { struct fdm *fdm; + struct reaper *reaper; const struct config *conf; pid_t slave; @@ -439,8 +441,9 @@ struct terminal { struct config; struct terminal *term_init( - const struct config *conf, struct fdm *fdm, struct wayland *wayl, - const char *foot_exe, const char *cwd, int argc, char *const *argv, + const struct config *conf, struct fdm *fdm, struct reaper *reaper, + struct wayland *wayl, const char *foot_exe, const char *cwd, + int argc, char *const *argv, void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data); bool term_shutdown(struct terminal *term);