summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordana <dana@dana.is>2026-05-20 13:48:41 -0500
committerdana <dana@dana.is>2026-05-23 00:26:42 -0500
commit8284a42bd3d0b7333f8d3c59cd6bb860c0edf499 (patch)
treed8ba25aea3fbdd6638b6153c10aa72da6b87f9e2
parentunposted: NEWS: update for w/52326 and w/52594 (diff)
downloadzsh-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--ChangeLog5
-rw-r--r--Src/jobs.c30
-rw-r--r--Test/W02jobs.ztst98
-rw-r--r--Test/W03jobparameters.ztst7
4 files changed, 120 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 3d072a21d..879186f38 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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