1
0
Fork 0
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:
Johnothan King 2020-08-06 18:53:25 -07:00 committed by GitHub
parent f9fdbfc9e9
commit 9de65210c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 45 additions and 7 deletions

6
NEWS
View file

@ -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

View file

@ -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,

View file

@ -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;

View file

@ -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 */

View file

@ -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

View file

@ -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);

View file

@ -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 */

View file

@ -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"

View file

@ -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))