Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: long-standing tty related issue: wrapped Emacs not suspended



On Tue, 25 Sep 2018 22:47:44 -0700
Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
But if you ^Z a function and then background it, the parent still
> believes it to be running even though it has instantly stopped:
> 
> % e
> zsh: suspended  e
> % bg
> [1]  + continued  e
> % jobs
> [1]  + running    e

To get this to work, I had to hack printjobs().  There's another hack in
printjobs to do pretty much the reverse --- if you're in the superjob
and the last job is suspended, treat it as running, because that's the
subshell that's waiting for the subjob so it's suspension isn't
relevant.  However, in this case I'm actually printing the subjob state
as the most relevant so that works around that --- this also means
"jobs" lists the correct process as suspended.

I've also added a printjob() to the point where the subjob is suspended
to make it reflect the fact that, as far as the user is concerned,
everything is associated with the superjob.

I would say we are in danger of disappearing up our own backsides but I
think that happened long ago.

pws

diff --git a/Src/jobs.c b/Src/jobs.c
index f64b46b..8103f5c 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -466,8 +466,10 @@ update_job(Job jn)
 	     * or to exit. So we have to send it a SIGTSTP. */
 	    int i;
 
+	    jn->stat |= STAT_CHANGED | STAT_STOPPED;
 	    if ((i = super_job(job))) {
-		killpg(jobtab[i].gleader, SIGTSTP);
+		Job sjn = &jobtab[i];
+		killpg(sjn->gleader, SIGTSTP);
 		/*
 		 * Job may already be stopped if it consists of only the
 		 * forked shell waiting for the subjob -- so mark as
@@ -475,9 +477,20 @@ update_job(Job jn)
 		 * crucially, the subjob, as the visible job used with
 		 * fg/bg is the superjob) a SIGCONT if we need it.
 		 */
-		jobtab[i].stat |= STAT_CHANGED | STAT_STOPPED;
+		sjn->stat |= STAT_CHANGED | STAT_STOPPED;
+		if (isset(NOTIFY) && (sjn->stat & STAT_LOCKED) &&
+		    !(sjn->stat & STAT_NOPRINT)) {
+		    /*
+		     * Print the subjob state, which we don't usually
+		     * do, so the user knows something has stopped.
+		     * So as not to be confusing, we actually output
+		     * the user-visible superjob.
+		     */
+		    if (printjob(sjn, !!isset(LONGLISTJOBS), 0) &&
+			zleactive)
+			zleentry(ZLE_CMD_REFRESH);
+		}
 	    }
-	    jn->stat |= STAT_CHANGED | STAT_STOPPED;
 	    return;
 	}
 	if (jn->stat & STAT_STOPPED)
@@ -1035,15 +1048,34 @@ printjob(Job jn, int lng, int synch)
 	   "bogus job number, jn = %L, jobtab = %L, oldjobtab = %L",
 	   (long)jn, (long)jobtab, (long)oldjobtab);
 
-    if (jn->stat & STAT_NOPRINT) {
+    if (jn->stat & STAT_NOPRINT)
 	skip_print = 1;
-    }
 
     if (lng < 0) {
 	conted = 1;
 	lng = !!isset(LONGLISTJOBS);
     }
 
+    if (jn->stat & STAT_SUPERJOB &&
+	jn->other)
+    {
+	Job sjn = &jobtab[jn->other];
+	if (sjn->stat & STAT_STOPPED)
+	{
+	    /*
+	     * A subjob is stopped, which will prevent further excution
+	     * of the superjob, which the user wants to know about.  So
+	     * report the status of the subjob as if it were the
+	     * user-visible superjob.
+	     *
+	     * TBD: there may be other times we want to do this
+	     * which would, for example, remove the need for the
+	     * hack at the top of the loop over processes just below.
+	     */
+	    jn = sjn;
+	}
+    }
+
 /* find length of longest signame, check to see */
 /* if we really need to print this job          */
 



Messages sorted by: Reverse Date, Date, Thread, Author