diff --git a/NEWS b/NEWS index 87a59cf54..c5f7fde08 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,12 @@ Any uppercase BUG_* names are modernish shell bug IDs. - Fixed a crash that occurred intermittently if 'set -b'/'set -o notify' is active and $PS1 contains a command substitution running an external command. +- Added the '${.sh.pid}' variable as an alternative to Bash's '$BASHPID'. + This variable is set to the current shell's PID, unlike '$$' (which is + set to the parent shell's PID). In virtual subshells '${.sh.pid}' is not + changed from its previous value, while in forked subshells '${.sh.pid}' + is set to the subshell's process ID. + 2020-08-05: - Fixed a bug in functions that caused ksh to crash when an array with an diff --git a/src/cmd/ksh93/data/variables.c b/src/cmd/ksh93/data/variables.c index f6646bac6..cadada6fd 100644 --- a/src/cmd/ksh93/data/variables.c +++ b/src/cmd/ksh93/data/variables.c @@ -99,6 +99,7 @@ const struct shtable2 shtab_variables[] = ".sh.stats", 0, (char*)0, ".sh.math", 0, (char*)0, ".sh.pool", 0, (char*)0, + ".sh.pid", NV_INTEGER|NV_NOFREE, (char*)0, "SHLVL", NV_INTEGER|NV_NOFREE|NV_EXPORT, (char*)0, #if SHOPT_MULTIBYTE "CSWIDTH", 0, (char*)0, diff --git a/src/cmd/ksh93/include/defs.h b/src/cmd/ksh93/include/defs.h index 816876559..67fc40be6 100644 --- a/src/cmd/ksh93/include/defs.h +++ b/src/cmd/ksh93/include/defs.h @@ -122,7 +122,8 @@ struct shared gid_t groupid; gid_t egroupid; pid_t pid; - int32_t ppid; + pid_t ppid; + pid_t current_pid; /* pid of the current ksh instance */ unsigned char sigruntime[2]; Namval_t *bltin_nodes; Namval_t *bltin_cmds; diff --git a/src/cmd/ksh93/include/variables.h b/src/cmd/ksh93/include/variables.h index c53e45f3b..6fff7921c 100644 --- a/src/cmd/ksh93/include/variables.h +++ b/src/cmd/ksh93/include/variables.h @@ -90,6 +90,7 @@ #define SH_STATS (shgd->bltin_nodes+60) #define SH_MATHNOD (shgd->bltin_nodes+61) #define SH_JOBPOOL (shgd->bltin_nodes+62) -#define SHLVL (shgd->bltin_nodes+63) +#define SH_PIDNOD (shgd->bltin_nodes+63) +#define SHLVL (shgd->bltin_nodes+64) #endif /* SH_VALNOD */ diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1 index 47230f48e..4ed099f6e 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -1664,6 +1664,16 @@ discipline function is invoked. .B .sh.subshell The current depth for subshells and command substitution. .TP +.B .sh.pid +Set to the process ID of the current shell. +This is distinct from +.B $$ +as in forked subshells this is set to the process ID of the +subshell instead of the parent shell's process ID. +In virtual subshells +.B .sh.pid +retains its previous value. +.TP .B .sh.value Set to the value of the variable at the time that the .B set diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c index 2ca5a3c72..6d3c8e8b8 100644 --- a/src/cmd/ksh93/sh/init.c +++ b/src/cmd/ksh93/sh/init.c @@ -1220,7 +1220,7 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit) beenhere = 1; shp = &sh; shgd = newof(0,struct shared,1,0); - shgd->pid = getpid(); + shgd->current_pid = shgd->pid = getpid(); shgd->ppid = getppid(); shgd->userid=getuid(); shgd->euserid=geteuid(); @@ -1832,6 +1832,7 @@ static Init_t *nv_init(Shell_t *shp) nv_stack(LANGNOD, &ip->LANG_init); #endif /* _hdr_locale */ (PPIDNOD)->nvalue.lp = (&shp->gd->ppid); + (SH_PIDNOD)->nvalue.lp = (&shp->gd->current_pid); (TMOUTNOD)->nvalue.lp = (&shp->st.tmout); (MCHKNOD)->nvalue.lp = (&sh_mailchk); (OPTINDNOD)->nvalue.lp = (&shp->st.optindex); diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index a031edcf2..255f47713 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -2917,6 +2917,9 @@ pid_t _sh_fork(Shell_t *shp,register pid_t parent,int flags,int *jobid) sh_onstate(SH_NOLOG); if (shp->fn_reset) shp->fn_depth = shp->fn_reset = 0; + /* Set ${.sh.pid} to the child process ID */ + shp->gd->current_pid = getpid(); + SH_PIDNOD->nvalue.lp = &shp->gd->current_pid; #if SHOPT_ACCT sh_accsusp(); #endif /* SHOPT_ACCT */ diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh index c49d109a3..468001697 100755 --- a/src/cmd/ksh93/tests/subshell.sh +++ b/src/cmd/ksh93/tests/subshell.sh @@ -747,14 +747,13 @@ v=$($SHELL $testvars) && [[ "$v" == "a= b= c=0" ]] || err_exit 'variables set in # ====== # Setting PATH in virtual subshell should trigger a fork; restoring PATH after leaving virtual subshell should not. -# TODO: it would be really nice to have a ${.sh.pid} for this sort of test (like $BASHPID on bash)... SHELL=$SHELL "$SHELL" -c ' ( - "$SHELL" -c "echo DEBUG \$PPID" + echo "DEBUG ${.sh.pid}" readonly PATH - "$SHELL" -c "echo DEBUG \$PPID" + echo "DEBUG ${.sh.pid}" ) - "$SHELL" -c "echo DEBUG \$PPID" + echo "DEBUG ${.sh.pid}" : extra command to disable "-c" exec optimization ' | awk '/^DEBUG/ { pid[NR] = $2; } END { exit !(pid[1] == pid[2] && pid[2] == pid[3]); }' \ || err_exit "setting PATH to readonly in subshell triggers an erroneous fork" diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh index cb4b7b6c6..96266856f 100755 --- a/src/cmd/ksh93/tests/variables.sh +++ b/src/cmd/ksh93/tests/variables.sh @@ -915,6 +915,7 @@ set -- \ ".sh.stats" \ ".sh.math" \ ".sh.pool" \ + ".sh.pid" \ "SHLVL" \ "CSWIDTH" @@ -991,5 +992,20 @@ $SHELL -c ' e=$? ((e == 1)) || err_exit "Failure in making one or more special variables readonly in a subshell (exit status $e)" +# ====== +# ${.sh.pid} should be the forked subshell's PID +( + ulimit -t unlimited + [[ ${.sh.pid} == $$ ]] +) && err_exit "\${.sh.pid} is the same as \$$ (both are $$)" + +# ${.sh.pid} should be the PID of the running job +echo ${.sh.pid} > "$tmp/jobpid" & +wait +[[ $(cat "$tmp/jobpid") == ${.sh.pid} ]] && err_exit "\${.sh.pid} is not set to a job's PID (expected $!, got $(cat "$tmp/jobpid"))" + +# ${.sh.pid} should be the same as $$ in the parent shell +[[ $$ == ${.sh.pid} ]] || err_exit "\${.sh.pid} and \$$ differ in the parent shell (expected $$, got ${.sh.pid})" + # ====== exit $((Errors<125?Errors:125))