Re: curjob in sub-shells?

dana <[email protected]>
Newsgroups gmane.comp.shells.zsh.devel
Message-ID <[email protected]>
On Wed 20 May 2026, at 03:42, Peter Stephenson wrote:
> From what I remember about fiddling with this ages aog, it's governed by
> the principle of least surprise: I think the point was that if you're in
> a subshell and reporting the current job the user probably wants to see
> what's in the parent shell.

ty. i think your 'oldjobtab' changes (w/17265) mostly addressed that aspect

here's the change i mentioned + some tests. + removed an uncharacteristic full
stop from an error message

dana


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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.