mirror of
				git://git.code.sf.net/p/cdesktopenv/code
				synced 2025-03-09 15:50:02 +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…
	
	Add table
		Add a link
		
	
		Reference in a new issue