From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18691 invoked from network); 7 Aug 2001 13:56:21 -0000 Received: from sunsite.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 7 Aug 2001 13:56:21 -0000 Received: (qmail 21386 invoked by alias); 7 Aug 2001 13:56:11 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 15591 Received: (qmail 21375 invoked from network); 7 Aug 2001 13:56:10 -0000 From: Sven Wischnowsky Date: Tue, 7 Aug 2001 15:55:53 +0200 (MET DST) Message-Id: <200108071355.PAA04130@beta.informatik.hu-berlin.de> To: zsh-workers@sunsite.dk Subject: Re: [falk@debian.org: Bug#107528: "while do done" gets into uninterruptable loop] In-Reply-To: <20010803105421.A14927@dman.com> Clint Adams wrote: > ... > > When I type "while do done", zsh loops without reacting to signals > like Ctrl-c, Ctrl-\, kill -TERM. No problem with "while :; do > done". The man page says > > while list do list done > > and list might be empty, so this should be valid syntax. > > I just noticed it returns immediately if $? happens to be non-zero. I > think it should always loop infinitely. In any case, it should be > interruptable. Hmhm. This is because in such a loop none of the flags that are tested in zhandler() ever gets set (line 519). The patch below looks stupid (and it may well be), but it's the easiest I can think of. I think I better not commit this until I get replies. (Most of it is re-indentation of that loop, there's just a tiny bit of added code at the top.) Another thing we could try is to just add `|| loops' to that line in signals.c but I'm not sure about what unwanted consequences that would have. Bye Sven Index: Src/loop.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/loop.c,v retrieving revision 1.5 diff -u -r1.5 loop.c --- Src/loop.c 2001/06/25 16:07:52 1.5 +++ Src/loop.c 2001/08/07 13:48:28 @@ -380,37 +380,53 @@ cmdpush(isuntil ? CS_UNTIL : CS_WHILE); loops++; loop = state->pc; - for (;;) { - state->pc = loop; - noerrexit = 1; - execlist(state, 1, 0); - noerrexit = olderrexit; - if (!((lastval == 0) ^ isuntil)) { - if (breaks) - breaks--; - lastval = oldval; - break; - } - if (retflag) { - lastval = oldval; - break; - } - execlist(state, 1, 0); - if (breaks) { - breaks--; - if (breaks || !contflag) - break; - contflag = 0; - } - if (errflag) { - lastval = 1; - break; - } - if (retflag) - break; - freeheap(); - oldval = lastval; - } + + if (loop[0] == WC_END && loop[1] == WC_END) { + + /* This is an empty loop. Make sure the signal handler sets the + * flags and then just wait for someone hitting ^C. */ + + int old_simple_pline = simple_pline; + + simple_pline = 1; + + while (!breaks) + ; + breaks--; + + simple_pline = old_simple_pline; + } else + for (;;) { + state->pc = loop; + noerrexit = 1; + execlist(state, 1, 0); + noerrexit = olderrexit; + if (!((lastval == 0) ^ isuntil)) { + if (breaks) + breaks--; + lastval = oldval; + break; + } + if (retflag) { + lastval = oldval; + break; + } + execlist(state, 1, 0); + if (breaks) { + breaks--; + if (breaks || !contflag) + break; + contflag = 0; + } + if (errflag) { + lastval = 1; + break; + } + if (retflag) + break; + freeheap(); + oldval = lastval; + } cmdpop(); popheap(); loops--; -- Sven Wischnowsky wischnow@informatik.hu-berlin.de