From b2556aa953b2339b79f0f6d22636c5eab742661d Mon Sep 17 00:00:00 2001 From: Scott Mcdermott Date: Wed, 10 Apr 2024 14:02:36 -0700 Subject: [PATCH] [fg] track master proc for suspend via pids, not term fds, for fork_on_start When ui.sessions.fork_on_start, we fork a process that has a different fdout than get_output_handle() (which has hardcoded fdout of 1), so it will never be considered term->master, yet this is the process we want to wake up in SIGTSTP handler. Since we cannot rely on term->master to determine if we are the master process, we instead move master_pid to be set explicitly at the places where we have information about whether our process is a master or a slave: first on start, then once the interlink determination has been made. master_pid has to be set in both parent and child, because both will get suspended and need to know which one needs to resume in background with SIGCONT (the master). We can't inherit from the parent because it's unknown at the time of fork. Previously, master_pid worked correctly with fork_on_start=0, -no-connect or -dump, but not with fork_on_start=1. See #287 for background. --- src/main/interlink.c | 13 +++++++++++-- src/main/main.c | 5 +++++ src/main/main.h | 1 + src/osdep/signals.c | 2 +- src/terminal/terminal.c | 8 -------- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/main/interlink.c b/src/main/interlink.c index 0bc2f6e8..82a7cd46 100644 --- a/src/main/interlink.c +++ b/src/main/interlink.c @@ -518,13 +518,15 @@ int init_interlink(void) { int fd = connect_to_af_unix(); - int pid; if (fd != -1 || remote_session_flags) return fd; parse_options_again(); if (get_opt_bool("ui.sessions.fork_on_start", NULL)) { + + pid_t pid; + pid = fork(); if (pid == -1) return -1; @@ -535,11 +537,18 @@ init_interlink(void) for (i = 1; i <= (MAX_BIND_TRIES+2); ++i) { fd = connect_to_af_unix(); - if (fd != -1) return fd; + if (fd != -1) { + master_pid = pid; + return fd; + } elinks_usleep(BIND_TRIES_DELAY * i); } return -1; } + /* child */ +#ifdef HAVE_GETPID + master_pid = getpid(); +#endif close_terminal_pipes(); } bind_to_af_unix(); diff --git a/src/main/main.c b/src/main/main.c index b0ec5666..1edda096 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -60,6 +60,8 @@ struct program program; +pid_t master_pid = 0; + static int ac; static char **av; static int init_b = 0; @@ -193,6 +195,9 @@ init(void) || get_cmd_opt_bool("source") || (fd = init_interlink()) == -1) { +#ifdef HAVE_GETPID + master_pid = getpid(); +#endif parse_options_again(); init_b = 1; init_modules(builtin_modules); diff --git a/src/main/main.h b/src/main/main.h index c8eb631e..fa6dcd8b 100644 --- a/src/main/main.h +++ b/src/main/main.h @@ -23,6 +23,7 @@ struct program { }; extern struct program program; +extern pid_t master_pid; void shrink_memory(int); void parse_options_again(void); diff --git a/src/osdep/signals.c b/src/osdep/signals.c index 6906320c..23473764 100644 --- a/src/osdep/signals.c +++ b/src/osdep/signals.c @@ -77,7 +77,7 @@ sig_tstp(struct terminal *term) block_itrm(); #if defined (SIGCONT) && defined(SIGTTOU) - if (master_pid) { + if (pid == master_pid) { pid_t newpid = fork(); if (!newpid) { int r; diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index 0f7f85c9..8245dd2f 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -54,8 +54,6 @@ INIT_LIST_OF(struct terminal, terminals); struct hash *temporary_files; static void check_if_no_terminal(void); -pid_t master_pid = 0; - void clean_temporary_files(void) { @@ -191,12 +189,6 @@ init_term(int fdin, int fdout) term->fdout = fdout; term->master = (term->fdout == get_output_handle()); -#ifdef HAVE_GETPID - if (term->master) { - master_pid = getpid(); - } -#endif - term->blocked = -1; get_terminal_name(name + 9);