On Sun, May 16, 2021 at 7:28 AM Bart Schaefer wrote: > > > Even more, if the user enters "while do; done" in an interactive zsh > > instance, the busy loop is not interruptible by ^C, ^\ or ^Z; the shell > > has to be killed via some external means. > > I can NOT reproduce this in the latest revision from git, but I can > reproduce it in zsh-5.8. Specifically, the shell is interruptible by ^C. I haven't attempted to bisect where this was introduced; there are no obvious deltas to signals.c, loop.c, or parse.c to explain it. It is impossible to interrupt the parser with SIGINT. zhandler is entered with signal queueing enabled; when signals are allowed again, zhandler is called again and we pass through this code: 675 if (list_pipe || chline || simple_pline) { 676 breaks = loops; 677 errflag |= ERRFLAG_INT; 678 inerrflush(); 679 check_cursh_sig(SIGINT); 680 } 681 lastval = 128 + SIGINT; Because we're still in the parser, none of (list_pipe || chline || simple_pline) is true, so we never set breaks or errflag, only lastval. I'm not immediately sure what to do about that; perhaps just move the errflag setting outside that test? The attached makes both "while do" and "do done" into parse errors; I didn't want to try messing with the tokenizer, so better solutions are welcome. I mention tokenizing because in "for do" the string "do" is not a token; "while do;" could conceivably mean to execute the command "do" as the test condition.