diff options
| author | dana <dana@dana.is> | 2026-05-20 13:48:41 -0500 |
|---|---|---|
| committer | dana <dana@dana.is> | 2026-05-23 00:26:42 -0500 |
| commit | 8284a42bd3d0b7333f8d3c59cd6bb860c0edf499 (patch) | |
| tree | d8ba25aea3fbdd6638b6153c10aa72da6b87f9e2 | |
| parent | unposted: NEWS: update for w/52326 and w/52594 (diff) | |
| download | zsh-8284a42bd3d0b7333f8d3c59cd6bb860c0edf499.tar zsh-8284a42bd3d0b7333f8d3c59cd6bb860c0edf499.tar.gz zsh-8284a42bd3d0b7333f8d3c59cd6bb860c0edf499.tar.bz2 zsh-8284a42bd3d0b7333f8d3c59cd6bb860c0edf499.tar.lz zsh-8284a42bd3d0b7333f8d3c59cd6bb860c0edf499.tar.xz zsh-8284a42bd3d0b7333f8d3c59cd6bb860c0edf499.tar.zst zsh-8284a42bd3d0b7333f8d3c59cd6bb860c0edf499.zip | |
54584: jobs: update curjob in sub-shells
| -rw-r--r-- | ChangeLog | 5 | ||||
| -rw-r--r-- | Src/jobs.c | 30 | ||||
| -rw-r--r-- | Test/W02jobs.ztst | 98 | ||||
| -rw-r--r-- | Test/W03jobparameters.ztst | 7 |
4 files changed, 120 insertions, 20 deletions
@@ -1,3 +1,8 @@ +2026-05-23 dana <dana@dana.is> + + * 54584: Src/jobs.c, Test/W02jobs.ztst, + Test/W03jobparameters.ztst: jobs: update curjob in sub-shells + 2026-05-22 dana <dana@dana.is> * unposted: NEWS: update for w/52326 and w/52594 diff --git a/Src/jobs.c b/Src/jobs.c index fc79a3f3a..2661ea0c1 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -1896,21 +1896,19 @@ spawnjob(void) Process pn; DPUTS(thisjob == -1, "No valid job in spawnjob."); - /* if we are not in a subshell */ - if (!subsh) { - if (curjob == -1 || !(jobtab[curjob].stat & STAT_STOPPED)) { - curjob = thisjob; - setprevjob(); - } else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED)) - prevjob = thisjob; - if (jobbing && jobtab[thisjob].procs) { - FILE *fout = shout ? shout : stdout; - fprintf(fout, "[%d]", thisjob); - for (pn = jobtab[thisjob].procs; pn; pn = pn->next) - fprintf(fout, " %ld", (long) pn->pid); - fprintf(fout, "\n"); - fflush(fout); - } + if (curjob == -1 || !(jobtab[curjob].stat & STAT_STOPPED)) { + curjob = thisjob; + setprevjob(); + } else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED)) + prevjob = thisjob; + + if (!subsh && jobbing && jobtab[thisjob].procs) { + FILE *fout = shout ? shout : stdout; + fprintf(fout, "[%d]", thisjob); + for (pn = jobtab[thisjob].procs; pn; pn = pn->next) + fprintf(fout, " %ld", (long) pn->pid); + fprintf(fout, "\n"); + fflush(fout); } if (!hasprocs(thisjob)) deletejob(jobtab + thisjob, 0); @@ -2460,7 +2458,7 @@ bin_fg(char *name, char **argv, Options ops, int func) if ((func == BIN_FG || func == BIN_BG) && !jobbing) { /* oops... maybe bg and fg should have been disabled? */ - zwarnnam(name, "no job control in this shell."); + zwarnnam(name, "no job control in this shell"); return 1; } diff --git a/Test/W02jobs.ztst b/Test/W02jobs.ztst index d52888dd9..135869d81 100644 --- a/Test/W02jobs.ztst +++ b/Test/W02jobs.ztst @@ -193,6 +193,104 @@ *>\[2] ? interrupt*sleep* *>\[1] ? kill*sleep* + zpty_start + zpty_input jobs + zpty_input '( jobs ); :' + zpty_stop +0:jobs with no jobs + + zpty_start + zpty_input 'sleep 2 &; ( jobs ); disown' + zpty_stop +0:jobs in sub-shell with job in parent shell +*>\[1] <-> +*>\[1] + * sleep 2 + + zpty_start + zpty_input '( sleep 2 &; jobs ); :' + zpty_stop +0:jobs in sub-shell with job in same shell +*>\[2] + * sleep 2 + + zpty_start + zpty_input 'sleep 2 &; jobs; ( sleep 3 &; jobs ); jobs; disown' + zpty_stop +0:jobs in sub-shell with job in parent + same shell +*>\[1] <-> +*>\[1] + * sleep 2 +*>\[2] + * sleep 3 +*>\[1] + * sleep 2 + + zpty_start + zpty_input '( sleep 2 &; sleep 3 &; jobs ); :' + zpty_stop +0:jobs in sub-shell with two jobs in same shell +*>\[2] - * sleep 2 +*>\[3] + * sleep 3 + + zpty_start + zpty_input 'sleep 2 &; sleep 3 &; disown; jobs; disown' + zpty_stop +0:disown current job +*>\[1] <-> +*>\[2] <-> +*>\[1] + * sleep 2 + + zpty_start + zpty_input disown + zpty_stop +0:disown with no jobs +>disown: no current job + + zpty_start + zpty_input 'sleep 2 &; ( disown ); jobs; disown' + zpty_stop +0:disown in sub-shell with job in parent shell +*>\[1] <-> +*>disown: can't manipulate jobs in subshell +*>\[1] + * sleep 2 + + zpty_start + zpty_input '( sleep 3 &; disown; jobs ); :' + zpty_stop +0:disown in sub-shell with job in same shell + + zpty_start + zpty_input 'sleep 2 &; ( sleep 3 &; disown; jobs ); jobs; disown' + zpty_stop +0:disown in sub-shell with job in parent + same shell +*>\[1] <-> +*>\[1] + * sleep 2 + +# @todo apparently testing suspended jobs with zpty is error-prone. see above +# zpty_start +# zpty_input 'sleep 3 &' +# zpty_input 'kill -STOP ${${=${ jobs -p }}[3]}' +# zpty_input 'disown' +# zpty_stop +#0:disown with stopped job +#*>\[1] <-> +#*>\[1] * suspended * sleep 3 +#*>disown: warning: job is suspended* + + zpty_start + zpty_input 'sleep 2 &; sleep 3 &|; jobs; disown' + zpty_input 'sleep 2 &; sleep 3 &!; jobs; disown' + zpty_stop +0:background and disown with &| and &! +*>\[1] <-> +*>\[1] * sleep 2 +*>\[1] <-> +*>\[1] * sleep 2 + + zpty_start + zpty_input '( fg ); :' + zpty_input '( bg ); :' + zpty_stop +0:fg + bg in sub-shell +*>fg: no job control in this shell +*>bg: no job control in this shell + %clean zmodload -ui zsh/zpty diff --git a/Test/W03jobparameters.ztst b/Test/W03jobparameters.ztst index a6f7a09b1..6b2b80d54 100644 --- a/Test/W03jobparameters.ztst +++ b/Test/W03jobparameters.ztst @@ -50,8 +50,7 @@ *>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. +# one has been started in the subshell. zpty_start zpty_input "MODULE_PATH=${(q)MODULE_PATH}" zpty_input 'sleep 3 &' @@ -63,7 +62,7 @@ >main *>running:+:*=running >sub -*>running::*=running +*>running:+:*=running *>zsh:*SIGHUPed* # output from zpty removes empty lines @@ -75,4 +74,4 @@ 0:$jobstate shows no job started in main shell but one started in subshell >main >sub -*>running::*=running +*>running:+:*=running |
