mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
term: don't double fork new terminal windows
Instead, register their PIDs with the new reaper module and let it handle them.
This commit is contained in:
parent
f49742ebba
commit
789617d5ad
6 changed files with 62 additions and 60 deletions
|
|
@ -25,6 +25,8 @@
|
||||||
line is empty.
|
line is empty.
|
||||||
* Number of lines to scroll is now always clamped to the number of
|
* Number of lines to scroll is now always clamped to the number of
|
||||||
lines in the scrolling region..
|
lines in the scrolling region..
|
||||||
|
* New terminal windows spawned with `ctrl`+`shift`+`n` is no longer
|
||||||
|
double forked.
|
||||||
|
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
|
||||||
4
main.c
4
main.c
|
|
@ -390,14 +390,14 @@ main(int argc, char *const *argv)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!as_server && (term = term_init(
|
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) {
|
&term_shutdown_cb, &shutdown_ctx)) == NULL) {
|
||||||
free(cwd);
|
free(cwd);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
free(cwd);
|
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;
|
goto out;
|
||||||
|
|
||||||
/* Remember to restore signals in slave */
|
/* Remember to restore signals in slave */
|
||||||
|
|
|
||||||
7
server.c
7
server.c
|
|
@ -24,6 +24,7 @@ struct client;
|
||||||
struct server {
|
struct server {
|
||||||
const struct config *conf;
|
const struct config *conf;
|
||||||
struct fdm *fdm;
|
struct fdm *fdm;
|
||||||
|
struct reaper *reaper;
|
||||||
struct wayland *wayl;
|
struct wayland *wayl;
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
@ -311,7 +312,7 @@ fdm_client(struct fdm *fdm, int fd, int events, void *data)
|
||||||
client->conf.startup_mode = STARTUP_FULLSCREEN;
|
client->conf.startup_mode = STARTUP_FULLSCREEN;
|
||||||
|
|
||||||
client->term = term_init(
|
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);
|
"footclient", cwd, argc, argv, &term_shutdown_handler, client);
|
||||||
|
|
||||||
if (client->term == NULL) {
|
if (client->term == NULL) {
|
||||||
|
|
@ -406,7 +407,8 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
struct server *
|
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);
|
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
|
@ -448,6 +450,7 @@ server_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl)
|
||||||
*server = (struct server) {
|
*server = (struct server) {
|
||||||
.conf = conf,
|
.conf = conf,
|
||||||
.fdm = fdm,
|
.fdm = fdm,
|
||||||
|
.reaper = reaper,
|
||||||
.wayl = wayl,
|
.wayl = wayl,
|
||||||
|
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
|
|
|
||||||
3
server.h
3
server.h
|
|
@ -5,5 +5,6 @@
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
|
|
||||||
struct server;
|
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);
|
void server_destroy(struct server *server);
|
||||||
|
|
|
||||||
99
terminal.c
99
terminal.c
|
|
@ -23,6 +23,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "grid.h"
|
#include "grid.h"
|
||||||
#include "quirks.h"
|
#include "quirks.h"
|
||||||
|
#include "reaper.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "selection.h"
|
#include "selection.h"
|
||||||
#include "sixel.h"
|
#include "sixel.h"
|
||||||
|
|
@ -714,8 +715,9 @@ load_fonts_from_conf(const struct terminal *term, const struct config *conf,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct terminal *
|
struct terminal *
|
||||||
term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
||||||
const char *foot_exe, const char *cwd, int argc, char *const *argv,
|
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)
|
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data)
|
||||||
{
|
{
|
||||||
int ptmx = -1;
|
int ptmx = -1;
|
||||||
|
|
@ -784,6 +786,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
||||||
/* Initialize configure-based terminal attributes */
|
/* Initialize configure-based terminal attributes */
|
||||||
*term = (struct terminal) {
|
*term = (struct terminal) {
|
||||||
.fdm = fdm,
|
.fdm = fdm,
|
||||||
|
.reaper = reaper,
|
||||||
.conf = conf,
|
.conf = conf,
|
||||||
.quit = false,
|
.quit = false,
|
||||||
.ptmx = ptmx,
|
.ptmx = ptmx,
|
||||||
|
|
@ -2221,69 +2224,59 @@ term_flash(struct terminal *term, unsigned duration_ms)
|
||||||
bool
|
bool
|
||||||
term_spawn_new(const struct terminal *term)
|
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();
|
pid_t pid = fork();
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
LOG_ERRNO("failed to fork new terminal");
|
LOG_ERRNO("failed to fork new terminal");
|
||||||
return false;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
/* Child */
|
/* Child */
|
||||||
int pipe_fds[2] = {-1, -1};
|
close(pipe_fds[0]);
|
||||||
if (pipe2(pipe_fds, O_CLOEXEC) < 0) {
|
if (chdir(term->cwd) < 0 ||
|
||||||
LOG_ERRNO("failed to create pipe");
|
execlp(term->foot_exe, term->foot_exe, NULL) < 0)
|
||||||
goto err;
|
{
|
||||||
}
|
(void)!write(pipe_fds[1], &errno, sizeof(errno));
|
||||||
|
|
||||||
/* 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);
|
|
||||||
_exit(errno);
|
_exit(errno);
|
||||||
}
|
}
|
||||||
|
assert(false);
|
||||||
/* 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]);
|
|
||||||
_exit(errno);
|
_exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
int result;
|
/* Parent */
|
||||||
waitpid(pid, &result, 0);
|
close(pipe_fds[1]);
|
||||||
return WIFEXITED(result) && WEXITSTATUS(result) == 0;
|
|
||||||
|
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
|
void
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
//#include "config.h"
|
//#include "config.h"
|
||||||
#include "fdm.h"
|
#include "fdm.h"
|
||||||
|
#include "reaper.h"
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
|
|
||||||
#define likely(c) __builtin_expect(!!(c), 1)
|
#define likely(c) __builtin_expect(!!(c), 1)
|
||||||
|
|
@ -206,6 +207,7 @@ enum term_surface {
|
||||||
|
|
||||||
struct terminal {
|
struct terminal {
|
||||||
struct fdm *fdm;
|
struct fdm *fdm;
|
||||||
|
struct reaper *reaper;
|
||||||
const struct config *conf;
|
const struct config *conf;
|
||||||
|
|
||||||
pid_t slave;
|
pid_t slave;
|
||||||
|
|
@ -439,8 +441,9 @@ struct terminal {
|
||||||
|
|
||||||
struct config;
|
struct config;
|
||||||
struct terminal *term_init(
|
struct terminal *term_init(
|
||||||
const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
||||||
const char *foot_exe, const char *cwd, int argc, char *const *argv,
|
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);
|
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data);
|
||||||
|
|
||||||
bool term_shutdown(struct terminal *term);
|
bool term_shutdown(struct terminal *term);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue