mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-13 11:42:21 +00:00
Add ${.sh.pid} as an alternative to $BASHPID (#109)
This variable is like Bash's $BASHPID, but in virtual subshells it will retain its previous value as virtual subshells don't fork. Both $BASHPID and ${.sh.pid} are different from $$ as the latter is only set to the parent shell's process ID (i.e. it isn't set to the process ID of the current subshell). src/cmd/ksh93/include/defs.h: - Add 'current_pid' for storing the current process ID at a valid memory address. - Change 'ppid' from 'int32_t' to 'pid_t', as the return value from 'getppid' is of the 'pid_t' data type. src/cmd/ksh93/data/variables.c, src/cmd/ksh93/include/variables.h, src/cmd/ksh93/sh/init.c, src/cmd/ksh93/sh/xec.c: - Add the ${.sh.pid} variable as an alternative to $BASHPID. The process ID is stored in a struct before ${.sh.pid} is set as environment variables are pointers that must point to a valid memory address. ${.sh.pid} is updated by the _sh_fork() function, which is called when ksh forks a new process with sh_fork() or sh_ntfork(). src/cmd/ksh93/tests/variables.sh: - Add ${.sh.pid} to the list of special variables and add three regression tests for ${.sh.pid}. src/cmd/ksh93/tests/subshell.sh: - Update the PATH forking regression test to use ${.sh.pid} and remove the TODO note.
This commit is contained in:
parent
f9fdbfc9e9
commit
9de65210c6
9 changed files with 45 additions and 7 deletions
6
NEWS
6
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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue