From 62cf88d0df8729b7dc971aa99e50e299bc56f13f Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Fri, 8 Jan 2021 17:33:04 +0000 Subject: [PATCH] Fix SIGHUP on termination (Solaris patch 260-22964338) This fixes the following bug filed with Solaris: "22964338 ksh93 appears to send SIGHUP to unrelated processes on occasion". It is fixed by applying this patch by Lijo George from the Solaris repo: https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/260-22964338.patch The ksh2020 upstream rejected this, but if it's in production use in Solaris, Solaris, it's probably good enough for 93u+m. If any breakage is left, it can be fixed later. https://github.com/att/ast/pull/1 src/cmd/ksh93/include/jobs.h, src/cmd/ksh93/sh/fault.c, src/cmd/ksh93/sh/jobs.c: - Use a new job_hup() function instead of job_kill() to send SIGHUP to job processes on termination. The new function checks if a job is in fact still live before issuing SIGHUP to it. --- src/cmd/ksh93/include/jobs.h | 1 + src/cmd/ksh93/sh/fault.c | 2 +- src/cmd/ksh93/sh/jobs.c | 48 ++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/cmd/ksh93/include/jobs.h b/src/cmd/ksh93/include/jobs.h index 8d4dc8503bab..90d9d2f8c7a2 100644 --- a/src/cmd/ksh93/include/jobs.h +++ b/src/cmd/ksh93/include/jobs.h @@ -179,6 +179,7 @@ extern void job_chldtrap(Shell_t*, const char*,int); extern int job_close(Shell_t*); extern int job_list(struct process*,int); extern int job_terminate(struct process*,int); + extern int job_hup(struct process *, int); extern int job_switch(struct process*,int); extern void job_fork(pid_t); extern int job_reap(int); diff --git a/src/cmd/ksh93/sh/fault.c b/src/cmd/ksh93/sh/fault.c index 786a5cf662a1..440e761d2ecc 100644 --- a/src/cmd/ksh93/sh/fault.c +++ b/src/cmd/ksh93/sh/fault.c @@ -634,7 +634,7 @@ void sh_done(void *ptr, register int sig) #endif #ifdef JOBS if((sh_isoption(SH_INTERACTIVE) && shp->login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP))) - job_walk(sfstderr,job_terminate,SIGHUP,NIL(char**)); + job_walk(sfstderr, job_hup, SIGHUP, NIL(char**)); #endif /* JOBS */ job_close(shp); if(nv_search("VMTRACE", shp->var_tree,0)) diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c index 71ab74e0f2af..a03e79d505ac 100644 --- a/src/cmd/ksh93/sh/jobs.c +++ b/src/cmd/ksh93/sh/jobs.c @@ -1072,6 +1072,54 @@ int job_kill(register struct process *pw,register int sig) return(r); } +/* + * Similar to job_kill, but dedicated to SIGHUP handling when session is + * being disconnected. + */ +int job_hup(struct process *pw, int sig) +{ + struct process *px; + pid_t pid; + int r; + NOT_USED(sig); + if(pw->p_pgrp == 0 || (pw->p_flag & P_DISOWN)) + return(0); + job_lock(); + if(pw->p_pgrp != 0) + { + int palive = 0; + for(px = pw; px != NULL; px = px->p_nxtproc) + { + if((px->p_flag & P_DONE) == 0) + { + palive = 1; + break; + } + } + /* + * If all the processes have died, there is no guarantee that + * p_pgrp is still the valid process group that we made, i.e., + * the PID may have been recycled and the same p_pgrp may have + * been assigned to unrelated processes. + */ + if(palive) + { + if(killpg(pw->p_pgrp, SIGHUP) >= 0) + job_unstop(pw); + } + } + for(; pw != NULL && pw->p_pgrp == 0; pw = pw->p_nxtproc) + { + if(pw->p_flag & P_DONE) + continue; + if(kill(pw->p_pid, SIGHUP) >= 0) + (void)kill(pw->p_pid, SIGCONT); + pw = pw->p_nxtproc; + } + job_unlock(); + return(0); +} + /* * Get process structure from first letters of jobname *