1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-12-29 16:25:35 +01:00

49906 (Bart), 49911: Fixes to querying jobs in subshell.

Don't attempt to query invalid job off end of table, resulting in
crashes from $jobtstates.

If background task started in subshell, look at tatsks within subshell
instead of main shell.  Document and add test.
This commit is contained in:
Peter Stephenson 2022-03-30 09:28:43 +01:00
parent f11227f78d
commit 98e4634086
6 changed files with 81 additions and 0 deletions

View file

@ -1,3 +1,11 @@
2022-03-30 Peter Stephenson <p.stephenson@samsung.com>
* 49906 (Bart), 49911: Doc/Zsh/builtins.yo,
Doc/Zsh/mod_parameter.yo, Src/exec.c, Src/jobs.c,
Test/W03jobparameters.ztst: Fix querying jobs in subshell.
Don't uery invalid job at end, if background job started in
subshell query jobs in subshell instead of main shell.
2022-03-30 Mikael Magnusson <mikachu@gmail.com> 2022-03-30 Mikael Magnusson <mikachu@gmail.com>
* 49893: Src/Zle/comp.h, Src/Zle/compcore.c: Fix comments for * 49893: Src/Zle/comp.h, Src/Zle/compcore.c: Fix comments for

View file

@ -1114,6 +1114,24 @@ The tt(-Z) option replaces the shell's argument and environment space with
the given string, truncated if necessary to fit. This will normally be the given string, truncated if necessary to fit. This will normally be
visible in tt(ps) (manref(ps)(1)) listings. This feature is typically visible in tt(ps) (manref(ps)(1)) listings. This feature is typically
used by daemons, to indicate their state. used by daemons, to indicate their state.
Full job control is only available in the top-level interactive shell,
not in commands run in the left hand side of pipelines or within
the tt(LPAR())var(...)tt(RPAR()) construct. However, a snapshot
of the job state at that point is taken, so it is still possible
to use the tt(jobs) builtin, or any parameter providing job information.
This gives information about the state of jobs at the point the subshell
was created. If background processes are created within the subshell,
then instead information about those processes is provided.
For example,
example(sleep 10 & # Job in background
LPAR() # Shell forks
jobs # Shows information about "sleep 10 &"
sleep 5 & # Process in background (no job control)
jobs # Shows information about "sleep 5 &"
RPAR())
) )
findex(kill) findex(kill)
cindex(killing jobs) cindex(killing jobs)

View file

@ -165,6 +165,8 @@ The keys of the associative arrays are usually valid job numbers,
and these are the values output with, for example, tt(${(k)jobdirs}). and these are the values output with, for example, tt(${(k)jobdirs}).
Non-numeric job references may be used when looking up a value; Non-numeric job references may be used when looking up a value;
for example, tt(${jobdirs[%+]}) refers to the current job. for example, tt(${jobdirs[%+]}) refers to the current job.
See the tt(jobs) builtin for how job information is provided in a subshell.
) )
vindex(jobtexts) vindex(jobtexts)
item(tt(jobtexts))( item(tt(jobtexts))(
@ -173,6 +175,8 @@ that were used to start the jobs.
Handling of the keys of the associative array is as described for Handling of the keys of the associative array is as described for
tt(jobdirs) above. tt(jobdirs) above.
See the tt(jobs) builtin for how job information is provided in a subshell.
) )
vindex(jobstates) vindex(jobstates)
item(tt(jobstates))( item(tt(jobstates))(
@ -189,6 +193,8 @@ the var(state) describes the state of that process.
Handling of the keys of the associative array is as described for Handling of the keys of the associative array is as described for
tt(jobdirs) above. tt(jobdirs) above.
See the tt(jobs) builtin for how job information is provided in a subshell.
) )
vindex(nameddirs) vindex(nameddirs)
item(tt(nameddirs))( item(tt(nameddirs))(

View file

@ -1689,6 +1689,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
execpline2(state, code, how, opipe[0], ipipe[1], last1); execpline2(state, code, how, opipe[0], ipipe[1], last1);
pline_level--; pline_level--;
if (how & Z_ASYNC) { if (how & Z_ASYNC) {
clearoldjobtab();
lastwj = newjob; lastwj = newjob;
if (thisjob == list_pipe_job) if (thisjob == list_pipe_job)

View file

@ -1718,8 +1718,15 @@ clearjobtab(int monitor)
/* Don't report any job we're part of */ /* Don't report any job we're part of */
if (thisjob != -1 && thisjob < oldmaxjob) if (thisjob != -1 && thisjob < oldmaxjob)
memset(oldjobtab+thisjob, 0, sizeof(struct job)); memset(oldjobtab+thisjob, 0, sizeof(struct job));
/* oldmaxjob is now the size of the table, but outside
* this function, it's used as a job number, which must
* be the largest index available in the table.
*/
--oldmaxjob;
} }
memset(jobtab, 0, jobtabsize * sizeof(struct job)); /* zero out table */ memset(jobtab, 0, jobtabsize * sizeof(struct job)); /* zero out table */
maxjob = 0; maxjob = 0;
@ -1733,6 +1740,18 @@ clearjobtab(int monitor)
thisjob = initjob(); thisjob = initjob();
} }
/* In a subshell, decide we want our own job table after all. */
/**/
mod_export void
clearoldjobtab(void)
{
if (oldjobtab)
free(oldjobtab);
oldjobtab = NULL;
oldmaxjob = 0;
}
static int initnewjob(int i) static int initnewjob(int i)
{ {
jobtab[i].stat = STAT_INUSE; jobtab[i].stat = STAT_INUSE;
@ -2449,6 +2468,7 @@ bin_fg(char *name, char **argv, Options ops, int func)
case BIN_BG: case BIN_BG:
case BIN_WAIT: case BIN_WAIT:
if (func == BIN_BG) { if (func == BIN_BG) {
clearoldjobtab();
jobtab[job].stat |= STAT_NOSTTY; jobtab[job].stat |= STAT_NOSTTY;
jobtab[job].stat &= ~STAT_CURSH; jobtab[job].stat &= ~STAT_CURSH;
} }

View file

@ -48,3 +48,31 @@
*>running:+:*=running *>running:+:*=running
*>running:+:*=running *>running:+:*=running
*>zsh:*SIGHUPed* *>zsh:*SIGHUPed*
# $jobstates refers to a job started in the main shell unless
# one has been started in the subshell. In the latter case,
# the subshell has no job control so the job is not marked as current.
zpty_start
zpty_input "MODULE_PATH=${(q)MODULE_PATH}"
zpty_input 'sleep 3 &'
zpty_input '(print main; print $jobstates; sleep 2& print sub; print $jobstates)'
zpty_input 'jobs -s'
zpty_stop
0:$jobstate shows one job started in main shell or one started in subshell
*>\[1] [0-9]##
>main
*>running:+:*=running
>sub
*>running::*=running
*>zsh:*SIGHUPed*
# output from zpty removes empty lines
zpty_start
zpty_input "MODULE_PATH=${(q)MODULE_PATH}"
zpty_input '(print main; print $jobstates; sleep 2& print sub; print $jobstates)'
zpty_input 'jobs -s'
zpty_stop
0:$jobstate shows no job started in main shell but one started in subshell
>main
>sub
*>running::*=running