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

Re: Zsh spins in endless loop with SIGHUP + read in zshexit



> On 13 May 2021 at 11:17 Jörg Sommer <joerg@xxxxxxxx> wrote:
> I'm using `read` in `zshexit` and when my terminal crashes (e.g. XTerm gets
> killed or ssh connection dies) Zsh spins in an endless loop until I kill it
> with SIGKILL (SIGTERM doesn't work).
> 
> ```
> zshexit()
> {
>     if [[ ${#${(M)${(f)"$(</proc/self/mountinfo)"}#*/ / rw,}} == 1 ]]
>     then
>         if read -rq junk"?Root filesystem is still read-write. Remount ro? (y/N) "
>         then
>             echo
>             mount -o remount,ro / || sleep 4
>         else
>             echo
>         fi
>     fi
> }
> ```

Yes, that's a clear bug.  Bart's been mulling over some error handling oddities
down here, not sure if that's one of them.  This is a bit of a special case ---
how about this?  Possibly other calls to zexit() might need similar treatment.

(More zsh-workers this time round, as it turns out.)

Warning: I'm currently in webmailland, too, but the diff is originally from a
proper Linux set up.

pws

diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 0561c3b3b..e8d1260b1 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -905,7 +905,8 @@ getbyte(long do_keytmout, int *timeout, int full)
 		if ((zlereadflags & ZLRF_IGNOREEOF) && icnt++ < 20)
 		    continue;
 		stopmsg = 1;
-		zexit(1, ZEXIT_NORMAL);
+		if (zexit(1, ZEXIT_NORMAL))
+		    return lastchar = EOF;
 	    }
 	    icnt = 0;
 	    if (errno == EINTR) {
@@ -928,14 +929,15 @@ getbyte(long do_keytmout, int *timeout, int full)
 	    } else if (errno != 0) {
 		zerr("error on TTY read: %e", errno);
 		stopmsg = 1;
-		zexit(1, ZEXIT_NORMAL);
+		if (zexit(1, ZEXIT_NORMAL))
+		    return lastchar = EOF;
 	    }
 	}
 	if (cc == '\r')		/* undo the exchange of \n and \r determined by */
 	    cc = '\n';		/* zsetterm() */
 	else if (cc == '\n')
 	    cc = '\r';
-
+	
 	ret = STOUC(cc);
     }
     /*
diff --git a/Src/builtin.c b/Src/builtin.c
index b7ceefd55..aefd1436f 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -5816,10 +5816,14 @@ _realexit(void)
  *   ZEXIT_DEFERRED if we can't actually exit yet (e.g., functions need
  *                  terminating) but should perform the usual interactive
  *                  tests.
+ *
+ * If this returns 1, we are already exiting the shell:  deeply
+ * embedded calls to this function should give up at that point
+ * and return an error indication.
  */
 
 /**/
-mod_export void
+mod_export int
 zexit(int val, enum zexit_t from_where)
 {
     /*
@@ -5829,7 +5833,7 @@ zexit(int val, enum zexit_t from_where)
      */
     exit_val = val;
     if (shell_exiting == -1)
-	return;
+	return 1;
 
     if (isset(MONITOR) && !stopmsg && from_where != ZEXIT_SIGNAL) {
 	scanjobs();    /* check if jobs need printing           */
@@ -5837,13 +5841,13 @@ zexit(int val, enum zexit_t from_where)
 	    checkjobs();   /* check if any jobs are running/stopped */
 	if (stopmsg) {
 	    stopmsg = 2;
-	    return;
+	    return 0;
 	}
     }
     /* Positive shell_exiting means we have been here before */
     if (from_where == ZEXIT_DEFERRED ||
 	(shell_exiting++ && from_where != ZEXIT_NORMAL))
-	return;
+	return 0;
 
     /*
      * We're now committed to exiting.  Set shell_exiting to -1 to
@@ -5893,6 +5897,8 @@ zexit(int val, enum zexit_t from_where)
 	_exit(exit_val);
     else
 	exit(exit_val);
+    /*NOTREACHED*/ /* I hope */
+    return 0;
 }
 
 /* . (dot), source */




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