zsh-workers
 help / color / mirror / code / Atom feed
* Re: zsh-3.1.9-dev-6 crashes occassionally
@ 2000-10-30  8:32 Sven Wischnowsky
  2000-10-30  9:56 ` Peter Stephenson
                   ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Sven Wischnowsky @ 2000-10-30  8:32 UTC (permalink / raw)
  To: zsh-workers


Thomas Koehler wrote:

> Hi there,
> I have the following problem with zsh-3.1.9-dev-6 on Debian GNU/Linux
> for i386:
> Sometimes, while trying to complete, zsh crashes and dumps core. In
> fact, the problem has been there for quite a while now, perhaps it has
> been there since the new completions system has been introduced - I
> don't know. The problem is: I can't reproduce the bug. It just happens
> to occur every once in a while.
> Well, this is not the only problem: Sometimes, zsh forgets its
> completion settings. I use this line in my .zshrc:
> zstyle ':completion:*' completer _complete _ignored _match _correct _approx=
> imate _prefix
> Now, sometimes, for some strange reason, zsh forgets to complete on tab
> and starts to _correct things right away: For example, I had a directory
> "abcdef" and a directory "abx" and typed "cd abc<TAB>" which resulted in
> "cd abx".

Thomas sent me his .zshrc, I tried, but couldn't reproduce it. But I
think I know where it comes from and why I never could reproduce it
(he reported it already quite some time ago, I think; or something
similar?).

Thomas uses a trap handler for the ALRM signal and with TMOUT=1 to
update his prompt. The trap handler uses several local parameters.
Since zsh invokes (shell-code) trap handler asynchronously from the
signal handler, this could easily mess up the parameter table if the
signal comes at a time when the completion code is playing with the
parameter table itself.

We talked about this several times already. We either need to protect
parts of the code (blocking signals there) or we should make the
signal handlers do as little as possible, setting only some flags or
something like that and call the trap handler shell-code somewhere
else where it can be called savely. We `decided' to use the second
solution, I think (and the first one is expensive and we have to find
all the right places and...).

We could also use a mixture: a global flag that tells the signal code
that it's save to invoke the trap handler right away but normally it
would only make them be called later. That flag could be set when zsh
is waiting for an external command, reading somethin or whatever.
(This could be a good reason to finally write a function that is
called everywhere zsh waits for something. And then we could allow
modules to hook into it or something.)

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
  2000-10-30  8:32 zsh-3.1.9-dev-6 crashes occassionally Sven Wischnowsky
@ 2000-10-30  9:56 ` Peter Stephenson
  2000-10-30 10:10 ` Thomas Köhler
  2000-10-30 16:18 ` Bart Schaefer
  2 siblings, 0 replies; 21+ messages in thread
From: Peter Stephenson @ 2000-10-30  9:56 UTC (permalink / raw)
  To: Zsh hackers list

Sven wrote:
> We talked about this several times already. We either need to protect
> parts of the code (blocking signals there) or we should make the
> signal handlers do as little as possible, setting only some flags or
> something like that and call the trap handler shell-code somewhere
> else where it can be called savely. We `decided' to use the second
> solution, I think (and the first one is expensive and we have to find
> all the right places and...).

Yes, and I was thinking about this recently, since I have a similar
requirement where it would fit the bill.

> We could also use a mixture: a global flag that tells the signal code
> that it's save to invoke the trap handler right away but normally it
> would only make them be called later. That flag could be set when zsh
> is waiting for an external command, reading somethin or whatever.
> (This could be a good reason to finally write a function that is
> called everywhere zsh waits for something. And then we could allow
> modules to hook into it or something.)

I was hoping for the ability for modules to define their own traps,
unconnected with real signals, which would allow them to have an
asynchronous part for internal processing and a part that calls shell code
defined by the user.  You can get the effect with a hook, but special traps
make the interface more uniform.

I was also thinking about the possibility of having trashzle() called
automatically --- then you can get your function to produce output
apparently asynchronously, but actually when the keyboard read is
interrupted, and have the screen tidied up.  This would be very useful, but
I'm not clear how to get it to work: if the function doesn't know it's
going to produce output till after, you couldn't call trashzle() till the
end, which might have unexpected effects due to the tty settings.  On the
other hand, if you call trashzle() at the start and the function doesn't
produce output, you have surprised the user for no reason.

Needless to say I haven't got around to doing any work on this.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
Cambridge Silicon Radio, Unit 300, Science Park, Milton Road,
Cambridge, CB4 0XL, UK                          Tel: +44 (0)1223 392070


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
  2000-10-30  8:32 zsh-3.1.9-dev-6 crashes occassionally Sven Wischnowsky
  2000-10-30  9:56 ` Peter Stephenson
@ 2000-10-30 10:10 ` Thomas Köhler
  2000-10-30 16:18 ` Bart Schaefer
  2 siblings, 0 replies; 21+ messages in thread
From: Thomas Köhler @ 2000-10-30 10:10 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 3063 bytes --]

On Mon, Oct 30, 2000 at 09:32:00AM +0100,
Sven Wischnowsky <wischnow@informatik.hu-berlin.de> wrote:
> Thomas Koehler wrote:
> 
> > Hi there,
> > I have the following problem with zsh-3.1.9-dev-6 on Debian GNU/Linux
> > for i386:
> > Sometimes, while trying to complete, zsh crashes and dumps core. In
> > fact, the problem has been there for quite a while now, perhaps it has
> > been there since the new completions system has been introduced - I
> > don't know. The problem is: I can't reproduce the bug. It just happens
> > to occur every once in a while.
> > Well, this is not the only problem: Sometimes, zsh forgets its
> > completion settings. I use this line in my .zshrc:
> > zstyle ':completion:*' completer _complete _ignored _match _correct _approx=
> > imate _prefix
> > Now, sometimes, for some strange reason, zsh forgets to complete on tab
> > and starts to _correct things right away: For example, I had a directory
> > "abcdef" and a directory "abx" and typed "cd abc<TAB>" which resulted in
> > "cd abx".
> 
> Thomas sent me his .zshrc, I tried, but couldn't reproduce it. But I
> think I know where it comes from and why I never could reproduce it
> (he reported it already quite some time ago, I think; or something
> similar?).

Yes, I reported this a while ago.

> Thomas uses a trap handler for the ALRM signal and with TMOUT=1 to
> update his prompt. The trap handler uses several local parameters.
> Since zsh invokes (shell-code) trap handler asynchronously from the
> signal handler, this could easily mess up the parameter table if the
> signal comes at a time when the completion code is playing with the
> parameter table itself.

Ugh.
Would it help if I'd change my signal handler not to use local
parameters?

> We talked about this several times already. We either need to protect
> parts of the code (blocking signals there) or we should make the
> signal handlers do as little as possible, setting only some flags or
> something like that and call the trap handler shell-code somewhere
> else where it can be called savely. We `decided' to use the second
> solution, I think (and the first one is expensive and we have to find
> all the right places and...).
> 
> We could also use a mixture: a global flag that tells the signal code
> that it's save to invoke the trap handler right away but normally it
> would only make them be called later. That flag could be set when zsh
> is waiting for an external command, reading somethin or whatever.
> (This could be a good reason to finally write a function that is
> called everywhere zsh waits for something. And then we could allow
> modules to hook into it or something.)

Sounds like a nice idea.

> Bye
>  Sven

CU,
Thomas

-- 
 Thomas Köhler Email:   jean-luc@picard.franken.de     | LCARS - Linux
     <><        WWW:     http://jeanluc-picard.de      | for Computers
                IRC:             jeanluc               | on All Real
               PGP public key available from Homepage! | Starships

[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
  2000-10-30  8:32 zsh-3.1.9-dev-6 crashes occassionally Sven Wischnowsky
  2000-10-30  9:56 ` Peter Stephenson
  2000-10-30 10:10 ` Thomas Köhler
@ 2000-10-30 16:18 ` Bart Schaefer
  2 siblings, 0 replies; 21+ messages in thread
From: Bart Schaefer @ 2000-10-30 16:18 UTC (permalink / raw)
  To: zsh-workers

On Oct 30,  9:32am, Sven Wischnowsky wrote:
} 
} Thomas uses a trap handler for the ALRM signal and with TMOUT=1 to
} update his prompt.  The trap handler uses several local parameters.
} Since zsh invokes (shell-code) trap handler asynchronously from the
} signal handler, this could easily mess up the parameter table if the
} signal comes at a time when the completion code is playing with the
} parameter table itself.

An easy way to find out -- at the top of _main_complete, add

	local TMOUT=0

which will shut off the alarm timer during the completion functions.  I
just tested this by setting up a TMOUT=1 refresh of my xterm title bar,
plus a completion function that does nothing but "sleep 5", and indeed
the title bar stopped updating for 5 seconds when I pressed TAB.

Zed does this same thing.

One other item of note:  For some strange reason, it's not possible to
alter TRAPxxx functions with "zed -f".  They come up in the editor, and
if you create one from scratch it sticks, but no changes that you make
to an already-existing TRAPxxx function are remembered.  No matter how
you exit zed, they always revert to their previous value.
 
} We talked about this several times already. We either need to protect
} parts of the code (blocking signals there) or we should make the
} signal handlers do as little as possible, setting only some flags or
} something like that and call the trap handler shell-code somewhere
} else where it can be called savely. We `decided' to use the second
} solution, I think (and the first one is expensive and we have to find
} all the right places and...).

I don't recall what the decision was, but setting a flag isn't enough
in the case of TMOUT/TRAPALRM -- you also have to force the blocking
read in getkey() to be interrupted and not restarted, or zsh will not
get to "somewhere else" in a timely fashion.  That means fooling with
setjmp/longjmp, most likely, which is an entire other can of worms we
might be better off not opening.
 
} We could also use a mixture: a global flag that tells the signal code
} that it's save to invoke the trap handler right away but normally it
} would only make them be called later. That flag could be set when zsh
} is waiting for an external command, reading somethin or whatever.

That would probably be enough to take care of the blocking-read issue.
However, our choice of "a safe place" to invoke the handler is still
going to have be made with some care -- it has to be a place (or more
than one) that is *guaranteed* to be reached quickly, and I just don't
see how we can possibly enforce that when arbitrary module code may get
involved.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
@ 2000-11-08 10:54 Sven Wischnowsky
  0 siblings, 0 replies; 21+ messages in thread
From: Sven Wischnowsky @ 2000-11-08 10:54 UTC (permalink / raw)
  To: zsh-workers


Thomas Koehler wrote:

> ...
> 
> So, if this patch will be committed, it's Peter's part to do so? :)

Or I commit mine and Peter puts his on top of it or the other way
round or...

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
  2000-11-08  9:41 Sven Wischnowsky
@ 2000-11-08 10:33 ` Thomas Köhler
  0 siblings, 0 replies; 21+ messages in thread
From: Thomas Köhler @ 2000-11-08 10:33 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 1884 bytes --]

On Wed, Nov 08, 2000 at 10:41:41AM +0100,
Sven Wischnowsky <wischnow@informatik.hu-berlin.de> wrote:
> 
> Bart Schaefer wrote:
> 
> > On Nov 1, 10:41am, Sven Wischnowsky wrote:
> > } 
> > } Here's the second version, still not-to-be-committed.
> > 
> > Of course, the question is, does this actually fix Thomas's crash?
> 
> I've seen Thomas' reply.
> 
> But: is this really the question? Without such a trap-handling delay
> and with the code not protecting critical code sections as it is now
> (without the patch), crashes like these can always happen. And the
> code is full of critical sections because there are many, many places
> where we access global data structures.

And lots of people will do funny things in their .zshrc and see
occassional crashes that nobody can explain. Uhm.

> However, the patch is so deep in the guts of zsh that I hesitate to
> decide if it should be committed, especially if Bart says things like
> the above ;-). I've been using it on my laptop ever since I posted it
> and didn't have any problems but I don't use TRAPALRM(), so that means 
> almost nothing (but Peter and I made sure the trap-tests still work
> correctly).

Hm. Collecting patches before recompiling etc, lots of work to do before
testing. Anybody to send me a full tar-ball with this patch applied?
Perhaps I can start testing this on Saturday or such...

> Anyway, Peter has the newest version of this patch, together with his
> trap-changes.

So, if this patch will be committed, it's Peter's part to do so? :)

> Bye
>  Sven

Ciao,
Thomas

-- 
 Thomas Köhler Email:   jean-luc@picard.franken.de     | LCARS - Linux
     <><        WWW:     http://jeanluc-picard.de      | for Computers
                IRC:             jeanluc               | on All Real
               PGP public key available from Homepage! | Starships

[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
@ 2000-11-08  9:41 Sven Wischnowsky
  2000-11-08 10:33 ` Thomas Köhler
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2000-11-08  9:41 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> On Nov 1, 10:41am, Sven Wischnowsky wrote:
> } 
> } Here's the second version, still not-to-be-committed.
> 
> Of course, the question is, does this actually fix Thomas's crash?

I've seen Thomas' reply.

But: is this really the question? Without such a trap-handling delay
and with the code not protecting critical code sections as it is now
(without the patch), crashes like these can always happen. And the
code is full of critical sections because there are many, many places
where we access global data structures.


However, the patch is so deep in the guts of zsh that I hesitate to
decide if it should be committed, especially if Bart says things like
the above ;-). I've been using it on my laptop ever since I posted it
and didn't have any problems but I don't use TRAPALRM(), so that means 
almost nothing (but Peter and I made sure the trap-tests still work
correctly).

Anyway, Peter has the newest version of this patch, together with his
trap-changes.


Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
  2000-11-03 15:42 ` Bart Schaefer
@ 2000-11-05 17:55   ` Thomas Köhler
  0 siblings, 0 replies; 21+ messages in thread
From: Thomas Köhler @ 2000-11-05 17:55 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 896 bytes --]

On Fri, Nov 03, 2000 at 03:42:30PM +0000,
Bart Schaefer <schaefer@candle.brasslantern.com> wrote:
> 
> On Nov 1, 10:41am, Sven Wischnowsky wrote:
> } 
> } Here's the second version, still not-to-be-committed.
> 
> Of course, the question is, does this actually fix Thomas's crash?

I don't know - I didn't have time to check this yet, nor will I have the
time for another one or two weeks. (The really ugly thing is that the
crash is not that easy to reproduce and may need a _long_ time until it
occurs, that's why Sven couldn't reproduce the crash while testing my
.zshrc).

Ciao,
Thomas

-- 
 Thomas Köhler Email:   jean-luc@picard.franken.de     | LCARS - Linux
     <><        WWW:     http://jeanluc-picard.de      | for Computers
                IRC:             jeanluc               | on All Real
               PGP public key available from Homepage! | Starships

[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
  2000-11-01  9:41 Sven Wischnowsky
@ 2000-11-03 15:42 ` Bart Schaefer
  2000-11-05 17:55   ` Thomas Köhler
  0 siblings, 1 reply; 21+ messages in thread
From: Bart Schaefer @ 2000-11-03 15:42 UTC (permalink / raw)
  To: zsh-workers; +Cc: Thomas Köhler

On Nov 1, 10:41am, Sven Wischnowsky wrote:
} 
} Here's the second version, still not-to-be-committed.

Of course, the question is, does this actually fix Thomas's crash?

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
@ 2000-11-01  9:41 Sven Wischnowsky
  2000-11-03 15:42 ` Bart Schaefer
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2000-11-01  9:41 UTC (permalink / raw)
  To: zsh-workers


Peter Stephenson wrote:

> Sven wrote:
> > +	ALLOWTRAPS {
> > +	    while ((r = read(SHTTY, &cc, 1)) != 1) {
> 
> I suppose you've thought this through more than I have, but wouldn't it be
> safer just to run traps every time the read returns?  I'm assuming a signal
> arriving will interrupt the read in any case, so as far as I can see it's
> pretty much equivalent in practise.  There's nothing too nasty in the block
> underneath, but it does call zrefresh() and attachtty() which are probably
> best treated as black boxes.

Here's the second version, still not-to-be-committed.

It uses ALLOWTRAPS { ... } DISALLOWTRAPS only around very short code
sequences. It even adds two utility functions `ztrapread' and
`ztrapwrite' which call read and write (not surprising) while allowing 
execution of trap handlers while they are waiting.

I've probably used these in too many places, for example in zftp. But
it's a problem: we want to allow `concurrent' execution of trap
handlers as often as possible when the shell may be waiting but if the 
trap handler calls the same code the `main thread' is currently
waiting at, it may or may not cause problems. Bleh. That's exactly the 
kind of decision I wanted to avoid. We could try to solve this at some 
central point, e.g. in execbuiltin() and make that return with a
non-zero status if the same builtin is currently being executed,
unless the structure describing the builtin contains a flag that says
that this builtin can be called from a trap handler even if it is
currently being executed by the normal control flow.

Bye
 Sven

diff -u -r ../oz/Src/Modules/zftp.c ./Src/Modules/zftp.c
--- ../oz/Src/Modules/zftp.c	Tue Oct 31 20:59:50 2000
+++ ./Src/Modules/zftp.c	Tue Oct 31 21:48:22 2000
@@ -801,7 +801,7 @@
 		cmdbuf[0] = (char)IAC;
 		cmdbuf[1] = (char)DONT;
 		cmdbuf[2] = ch;
-		write(zfsess->cfd, cmdbuf, 3);
+		ztrapwrite(zfsess->cfd, cmdbuf, 3);
 		continue;
 
 	    case DO:
@@ -811,7 +811,7 @@
 		cmdbuf[0] = (char)IAC;
 		cmdbuf[1] = (char)WONT;
 		cmdbuf[2] = ch;
-		write(zfsess->cfd, cmdbuf, 3);
+		ztrapwrite(zfsess->cfd, cmdbuf, 3);
 		continue;
 
 	    case EOF:
@@ -996,7 +996,7 @@
 	return 6;
     }
     zfalarm(tmout);
-    ret = write(zfsess->cfd, cmd, strlen(cmd));
+    ret = ztrapwrite(zfsess->cfd, cmd, strlen(cmd));
     alarm(0);
 
     if (ret <= 0) {
@@ -1470,7 +1470,7 @@
     int ret;
 
     if (!tmout)
-	return read(fd, bf, sz);
+	return ztrapread(fd, bf, sz);
 
     if (setjmp(zfalrmbuf)) {
 	alarm(0);
@@ -1479,7 +1479,7 @@
     }
     zfalarm(tmout);
 
-    ret = read(fd, bf, sz);
+    ret = ztrapread(fd, bf, sz);
 
     /* we don't bother turning off the whole alarm mechanism here */
     alarm(0);
@@ -1495,7 +1495,7 @@
     int ret;
 
     if (!tmout)
-	return write(fd, bf, sz);
+	return ztrapwrite(fd, bf, sz);
 
     if (setjmp(zfalrmbuf)) {
 	alarm(0);
@@ -1504,7 +1504,7 @@
     }
     zfalarm(tmout);
 
-    ret = write(fd, bf, sz);
+    ret = ztrapwrite(fd, bf, sz);
 
     /* we don't bother turning off the whole alarm mechanism here */
     alarm(0);
@@ -2846,7 +2846,7 @@
 	if (!zfnopen) {
 	    /* Write the final status in case this is a subshell */
 	    lseek(zfstatfd, zfsessno*sizeof(int), 0);
-	    write(zfstatfd, zfstatusp+zfsessno, sizeof(int));
+	    ztrapwrite(zfstatfd, zfstatusp+zfsessno, sizeof(int));
 
 	    close(zfstatfd);
 	    zfstatfd = -1;
@@ -3123,7 +3123,7 @@
 	/* Get the status in case it was set by a forked process */
 	int oldstatus = zfstatusp[zfsessno];
 	lseek(zfstatfd, 0, 0);
-	read(zfstatfd, zfstatusp, sizeof(int)*zfsesscnt);
+	ztrapread(zfstatfd, zfstatusp, sizeof(int)*zfsesscnt);
 	if (zfsess->cfd != -1 && (zfstatusp[zfsessno] & ZFST_CLOS)) {
 	    /* got closed in subshell without us knowing */
 	    zcfinish = 2;
@@ -3212,7 +3212,7 @@
 	 * but only for the active session.
 	 */
 	lseek(zfstatfd, zfsessno*sizeof(int), 0);
-	write(zfstatfd, zfstatusp+zfsessno, sizeof(int));
+	ztrapwrite(zfstatfd, zfstatusp+zfsessno, sizeof(int));
     }
     return ret;
 }
diff -u -r ../oz/Src/Modules/zpty.c ./Src/Modules/zpty.c
--- ../oz/Src/Modules/zpty.c	Tue Oct 31 20:59:50 2000
+++ ./Src/Modules/zpty.c	Tue Oct 31 21:49:48 2000
@@ -489,7 +489,7 @@
 	    if (cmd->fin)
 		break;
 	}
-	if ((ret = read(cmd->fd, buf + used, 1)) == 1) {
+	if ((ret = ztrapread(cmd->fd, buf + used, 1)) == 1) {
 	    if (++used == blen) {
 		buf = hrealloc(buf, blen, blen << 1);
 		blen <<= 1;
@@ -520,7 +520,7 @@
 	setsparam(*args, ztrdup(metafy(buf, used, META_HREALLOC)));
     else {
 	fflush(stdout);
-	write(1, buf, used);
+	ztrapwrite(1, buf, used);
     }
     return (used ? 0 : cmd->fin + 1);
 }
@@ -532,7 +532,7 @@
 
     for (; !errflag && !breaks && !retflag && !contflag && len;
 	 len -= written, s += written) {
-	if ((written = write(cmd->fd, s, len)) < 0 && cmd->nblock &&
+	if ((written = ztrapwrite(cmd->fd, s, len)) < 0 && cmd->nblock &&
 #ifdef EWOULDBLOCK
 	    errno == EWOULDBLOCK
 #else
@@ -574,7 +574,7 @@
 	int n;
 	char buf[BUFSIZ];
 
-	while ((n = read(0, buf, BUFSIZ)) > 0)
+	while ((n = ztrapread(0, buf, BUFSIZ)) > 0)
 	    if (ptywritestr(cmd, buf, n))
 		return 1;
     }
diff -u -r ../oz/Src/Zle/zle_main.c ./Src/Zle/zle_main.c
--- ../oz/Src/Zle/zle_main.c	Tue Oct 31 20:59:48 2000
+++ ./Src/Zle/zle_main.c	Tue Oct 31 21:43:40 2000
@@ -313,11 +313,17 @@
 breakread(int fd, char *buf, int n)
 {
     fd_set f;
+    int ret;
 
     FD_ZERO(&f);
     FD_SET(fd, &f);
-    return (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
-	    EOF : read(fd, buf, n));
+
+    ALLOWTRAPS {
+	ret = (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
+	       EOF : read(fd, buf, n));
+    } DISALLOWTRAPS;
+
+    return ret;
 }
 
 # define read    breakread
@@ -388,7 +394,7 @@
 #  else
 	    ioctl(SHTTY, TCSETA, &ti.tio);
 #  endif
-	    r = read(SHTTY, &cc, 1);
+	    r = ztrapread(SHTTY, &cc, 1);
 #  ifdef HAVE_TERMIOS_H
 	    tcsetattr(SHTTY, TCSANOW, &shttyinfo.tio);
 #  else
@@ -398,7 +404,10 @@
 # endif
 #endif
 	}
-	while ((r = read(SHTTY, &cc, 1)) != 1) {
+	for (;;) {
+	    r = ztrapread(SHTTY, &cc, 1);
+	    if (r == 1)
+		break;
 	    if (r == 0) {
 		/* The test for IGNOREEOF was added to make zsh ignore ^Ds
 		   that were typed while commands are running.  Unfortuantely
diff -u -r ../oz/Src/builtin.c ./Src/builtin.c
--- ../oz/Src/builtin.c	Tue Oct 31 20:59:46 2000
+++ ./Src/builtin.c	Tue Oct 31 21:38:41 2000
@@ -3218,7 +3218,7 @@
 	    checkjobs();   /* check if any jobs are running/stopped */
 	if (stopmsg) {
 	    stopmsg = 2;
-	    LASTALLOC_RETURN;
+	    return;
 	}
     }
     if (in_exit++ && from_signal)
@@ -3240,7 +3240,7 @@
 	}
     }
     if (sigtrapped[SIGEXIT])
-	dotrap(SIGEXIT);
+	dotrap(SIGEXIT, 1);
     runhookdef(EXITHOOK, NULL);
     if (mypid != getpid())
 	_exit(val);
@@ -3486,7 +3486,7 @@
 		    *bptr = readchar;
 		    val = 1;
 		    readchar = -1;
-		} else if ((val = read(readfd, bptr, nchars)) <= 0)
+		} else if ((val = ztrapread(readfd, bptr, nchars)) <= 0)
 		    break;
 	    
 		/* decrement number of characters read from number required */
@@ -3500,7 +3500,7 @@
 	if (!izle && !ops['u'] && !ops['p']) {
 	    /* dispose of result appropriately, etc. */
 	    if (isem)
-		while (val > 0 && read(SHTTY, &d, 1) == 1 && d != '\n');
+		while (val > 0 && ztrapread(SHTTY, &d, 1) == 1 && d != '\n');
 	    else
 		settyinfo(&shttyinfo);
 	    if (haso) {
@@ -3733,6 +3733,7 @@
 zread(int izle, int *readchar)
 {
     char cc, retry = 0;
+    int ret;
 
     if (izle) {
 	int c = getkeyptr(0);
@@ -3756,7 +3757,8 @@
     }
     for (;;) {
 	/* read a character from readfd */
-	switch (read(readfd, &cc, 1)) {
+	ret = ztrapread(readfd, &cc, 1);
+	switch (ret) {
 	case 1:
 	    /* return the character read */
 	    return STOUC(cc);
diff -u -r ../oz/Src/exec.c ./Src/exec.c
--- ../oz/Src/exec.c	Tue Oct 31 20:59:46 2000
+++ ./Src/exec.c	Tue Oct 31 21:00:05 2000
@@ -738,6 +738,7 @@
 execsimple(Estate state)
 {
     wordcode code = *state->pc++;
+    int lv;
 
     if (errflag)
 	return (lastval = 1);
@@ -754,9 +755,13 @@
 	    fputc('\n', xtrerr);
 	    fflush(xtrerr);
 	}
-	return (lastval = (errflag ? errflag : cmdoutval));
+	lv = (errflag ? errflag : cmdoutval);
     } else
-	return (lastval = (execfuncs[code - WC_CURSH])(state, 0));
+	lv = (execfuncs[code - WC_CURSH])(state, 0);
+
+    RUNTRAPS();
+
+    return lastval = lv;
 }
 
 /* Main routine for executing a list.                                *
@@ -887,19 +892,19 @@
 	noerrexit = oldnoerrexit;
 
 	if (sigtrapped[SIGDEBUG])
-	    dotrap(SIGDEBUG);
+	    dotrap(SIGDEBUG, 1);
 
 	/* Check whether we are suppressing traps/errexit *
 	 * (typically in init scripts) and if we haven't  *
 	 * already performed them for this sublist.       */
 	if (!noerrexit && !donetrap) {
 	    if (sigtrapped[SIGZERR] && lastval) {
-		dotrap(SIGZERR);
+		dotrap(SIGZERR, 1);
 		donetrap = 1;
 	    }
 	    if (lastval && isset(ERREXIT)) {
 		if (sigtrapped[SIGEXIT])
-		    dotrap(SIGEXIT);
+		    dotrap(SIGEXIT, 1);
 		if (mypid != getpid())
 		    _exit(lastval);
 		else
@@ -1181,9 +1186,10 @@
 	else
 	    list_pipe_text[0] = '\0';
     }
-    if (WC_PIPE_TYPE(pcode) == WC_PIPE_END)
+    if (WC_PIPE_TYPE(pcode) == WC_PIPE_END) {
 	execcmd(state, input, output, how, last1 ? 1 : 2);
-    else {
+	RUNTRAPS();
+    } else {
 	int old_list_pipe = list_pipe;
 	Wordcode next = state->pc + (*state->pc);
 	wordcode code;
@@ -1218,12 +1224,14 @@
 		entersubsh(how, 2, 0);
 		close(synch[1]);
 		execcmd(state, input, pipes[1], how, 0);
+		RUNTRAPS();
 		_exit(lastval);
 	    }
 	} else {
 	    /* otherwise just do the pipeline normally. */
 	    subsh_close = pipes[0];
 	    execcmd(state, input, pipes[1], how, 0);
+	    RUNTRAPS();
 	}
 	zclose(pipes[1]);
 	state->pc = next;
diff -u -r ../oz/Src/init.c ./Src/init.c
--- ../oz/Src/init.c	Tue Oct 31 20:59:46 2000
+++ ./Src/init.c	Tue Oct 31 21:00:47 2000
@@ -170,7 +170,7 @@
 	}
 	if (isset(SINGLECOMMAND) && toplevel) {
 	    if (sigtrapped[SIGEXIT])
-		dotrap(SIGEXIT);
+		dotrap(SIGEXIT, 1);
 	    exit(lastval);
 	}
 	if (justonce)
@@ -1107,6 +1107,7 @@
     pptbuf = unmetafy(promptexpand(lp, 0, NULL, NULL), &pptlen);
     write(2, (WRITE_ARG_2_T)pptbuf, pptlen);
     free(pptbuf);
+
     return (unsigned char *)shingetline();
 }
 
diff -u -r ../oz/Src/input.c ./Src/input.c
--- ../oz/Src/input.c	Tue Oct 31 20:59:46 2000
+++ ./Src/input.c	Tue Oct 31 21:01:15 2000
@@ -141,7 +141,9 @@
     for (;;) {
 	do {
 	    errno = 0;
-	    c = fgetc(bshin);
+	    ALLOWTRAPS {
+		c = fgetc(bshin);
+	    } DISALLOWTRAPS;
 	} while (c < 0 && errno == EINTR);
 	if (c < 0 || c == '\n') {
 	    if (c == '\n')
diff -u -r ../oz/Src/jobs.c ./Src/jobs.c
--- ../oz/Src/jobs.c	Tue Oct 31 20:59:46 2000
+++ ./Src/jobs.c	Tue Oct 31 21:09:18 2000
@@ -378,7 +378,7 @@
 	    zrefresh();
     }
     if (sigtrapped[SIGCHLD] && job != thisjob)
-	dotrap(SIGCHLD);
+	dotrap(SIGCHLD, 0);
 
     /* When MONITOR is set, the foreground process runs in a different *
      * process group from the shell, so the shell will not receive     *
@@ -389,7 +389,7 @@
 
 	if (sig == SIGINT || sig == SIGQUIT) {
 	    if (sigtrapped[sig]) {
-		dotrap(sig);
+		dotrap(sig, 0);
 		/* We keep the errflag as set or not by dotrap.
 		 * This is to fulfil the promise to carry on
 		 * with the jobs if trap returns zero.
@@ -878,7 +878,9 @@
 	else
 	    kill(pid, SIGCONT);
 
-	child_suspend(SIGINT);
+	ALLOWTRAPS {
+	    child_suspend(SIGINT);
+	} DISALLOWTRAPS;
 	child_block();
     }
     child_unblock();
@@ -900,7 +902,9 @@
 	while (!errflag && jn->stat &&
 	       !(jn->stat & STAT_DONE) &&
 	       !(interact && (jn->stat & STAT_STOPPED))) {
-	    child_suspend(sig);
+	    ALLOWTRAPS {
+		child_suspend(sig);
+	    } DISALLOWTRAPS;
 	    /* Commenting this out makes ^C-ing a job started by a function
 	       stop the whole function again.  But I guess it will stop
 	       something else from working properly, we have to find out
@@ -1363,7 +1367,7 @@
 		killjb(jobtab + job, SIGCONT);
 	    }
 	    if (func == BIN_WAIT)
-	        waitjob(job, SIGINT);
+		waitjob(job, SIGINT);
 	    if (func != BIN_BG) {
 		waitjobs();
 		retval = lastval2;
diff -u -r ../oz/Src/signals.c ./Src/signals.c
--- ../oz/Src/signals.c	Tue Oct 31 20:59:47 2000
+++ ./Src/signals.c	Tue Oct 31 21:00:05 2000
@@ -497,7 +497,7 @@
  
     case SIGHUP:
         if (sigtrapped[SIGHUP])
-            dotrap(SIGHUP);
+            dotrap(SIGHUP, 0);
         else {
             stopmsg = 1;
             zexit(SIGHUP, 1);
@@ -506,7 +506,7 @@
  
     case SIGINT:
         if (sigtrapped[SIGINT])
-            dotrap(SIGINT);
+            dotrap(SIGINT, 0);
         else {
 	    if ((isset(PRIVILEGED) || isset(RESTRICTED)) &&
 		isset(INTERACTIVE) && noerrexit < 0)
@@ -523,14 +523,14 @@
     case SIGWINCH:
         adjustwinsize(1);  /* check window size and adjust */
 	if (sigtrapped[SIGWINCH])
-	    dotrap(SIGWINCH);
+	    dotrap(SIGWINCH, 0);
         break;
 #endif
 
     case SIGALRM:
         if (sigtrapped[SIGALRM]) {
 	    int tmout;
-            dotrap(SIGALRM);
+            dotrap(SIGALRM, 0);
 
 	    if ((tmout = getiparam("TMOUT")))
 		alarm(tmout);           /* reset the alarm */
@@ -549,7 +549,7 @@
         break;
  
     default:
-        dotrap(sig);
+        dotrap(sig, 0);
         break;
     }   /* end of switch(sig) */
  
@@ -907,7 +907,9 @@
      * function will test for this, but this way we keep status flags *
      * intact without working too hard.  Special cases (e.g. calling  *
      * a trap for SIGINT after the error flag was set) are handled    *
-     * by the calling code.  (PWS 1995/06/08).			      */
+     * by the calling code.  (PWS 1995/06/08).			      *
+     *                                                                *
+     * This test is now replicated in dotrap().                       */
     if ((*sigtr & ZSIG_IGNORED) || !sigfn || errflag)
         return;
 
@@ -957,11 +959,56 @@
 	*sigtr &= ~ZSIG_IGNORED;
 }
 
-/* Standard call to execute a trap for a given signal */
+/* != 0 if trap handlers can be called immediately */
+
+/**/
+mod_export int trapsallowed;
+
+/* Queued traps and allocated length of queue. */
+
+static int *trapqueue, trapqlen;
+
+/* Number of used slots in trap queue. */
+
+/**/
+mod_export int trapqused;
+
+/* Standard call to execute a trap for a given signal.  The second
+ * argument should be zero if we may need to put the trap on the queue
+ * and 1 if it may be called immediately.  It should never be set to
+ * anything less than zero, that's used internally. */
 
 /**/
 void
-dotrap(int sig)
+dotrap(int sig, int now)
 {
-    dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
+    /* Copied from dotrapargs(). */
+    if ((sigtrapped[sig] & ZSIG_IGNORED) || !sigfuncs[sig] || errflag)
+	return;
+
+    if (now || trapsallowed) {
+	if (now < 0)
+	    RUNTRAPS();
+	dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
+    } else {
+	if (trapqlen == trapqused)
+	    trapqueue = (int *) zrealloc(trapqueue, (trapqlen += 32));
+	trapqueue[trapqused++] = sig;
+    }
+}
+
+/**/
+mod_export void
+doqueuedtraps(void)
+{
+    int sig, ota = trapsallowed;
+
+    trapsallowed = 1;
+    while (trapqused) {
+	trapqused--;
+	sig = *trapqueue;
+	memcpy(trapqueue, trapqueue + 1, trapqused * sizeof(int));
+	dotrap(sig, -1);
+    }
+    trapsallowed = ota;
 }
diff -u -r ../oz/Src/signals.h ./Src/signals.h
--- ../oz/Src/signals.h	Tue Oct 31 20:59:47 2000
+++ ./Src/signals.h	Tue Oct 31 21:00:05 2000
@@ -118,3 +118,8 @@
 extern sigset_t signal_unblock _((sigset_t));
 #endif   /* POSIX_SIGNALS */
 
+#define RUNTRAPS() do { if (trapqused) doqueuedtraps(); } while (0)
+#define ALLOWTRAPS do { RUNTRAPS(); trapsallowed++; do
+#define DISALLOWTRAPS while (0); RUNTRAPS(); trapsallowed--; } while (0)
+#define ALLOWTRAPS_RETURN(V) \
+    do { RUNTRAPS(); trapsallowed--; return (V); } while (0)
diff -u -r ../oz/Src/utils.c ./Src/utils.c
--- ../oz/Src/utils.c	Tue Oct 31 20:59:47 2000
+++ ./Src/utils.c	Tue Oct 31 21:46:30 2000
@@ -1419,12 +1419,38 @@
 }
 
 /**/
+mod_export int
+ztrapread(int fd, char *buf, int len)
+{
+    int ret;
+
+    ALLOWTRAPS {
+	ret = read(fd, buf, len);
+    } DISALLOWTRAPS;
+
+    return ret;
+}
+
+/**/
+mod_export int
+ztrapwrite(int fd, char *buf, int len)
+{
+    int ret;
+
+    ALLOWTRAPS {
+	ret = write(fd, buf, len);
+    } DISALLOWTRAPS;
+
+    return ret;
+}
+
+/**/
 int
 read1char(void)
 {
     char c;
 
-    while (read(SHTTY, &c, 1) != 1) {
+    while (ztrapread(SHTTY, &c, 1) != 1) {
 	if (errno != EINTR || errflag || retflag || breaks || contflag)
 	    return -1;
     }
@@ -1441,7 +1467,7 @@
     ioctl(SHTTY, FIONREAD, (char *)&val);
     if (purge) {
 	for (; val; val--)
-	    read(SHTTY, &c, 1);
+	    ztrapread(SHTTY, &c, 1);
     }
 #endif
 
diff -u -r ../oz/Src/zsh.h ./Src/zsh.h
--- ../oz/Src/zsh.h	Tue Oct 31 20:59:47 2000
+++ ./Src/zsh.h	Tue Oct 31 21:00:05 2000
@@ -1627,8 +1627,6 @@
 #endif
 ;
 
-# define LASTALLOC_RETURN return
-
 # define NEWHEAPS(h)    do { Heap _switch_oldheaps = h = new_heaps(); do
 # define OLDHEAPS       while (0); old_heaps(_switch_oldheaps); } while (0);
 

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: zsh-3.1.9-dev-6 crashes occassionally
  2000-10-31 15:25     ` Bart Schaefer
@ 2000-10-31 15:43       ` Andrej Borsenkow
  0 siblings, 0 replies; 21+ messages in thread
From: Andrej Borsenkow @ 2000-10-31 15:43 UTC (permalink / raw)
  To: Zsh hackers list

>
> On Oct 31,  3:01pm, Sven Wischnowsky wrote:
> }
> } Unless someone knows of a system where signals don't interrupt things
> } like read.
>
> Ever heard of BSD restartable system calls?
>


I was about to make the same reply but then I realized, Sven was asking about
read _blocking_ interrupts. At least, that is how I understand the above
statement.

-andrej


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
@ 2000-10-31 15:42 Sven Wischnowsky
  0 siblings, 0 replies; 21+ messages in thread
From: Sven Wischnowsky @ 2000-10-31 15:42 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> On Oct 31,  1:51pm, Peter Stephenson wrote:
> } Subject: Re: zsh-3.1.9-dev-6 crashes occassionally
> }
> } Sven wrote:
> } > +	ALLOWTRAPS {
> } > +	    while ((r = read(SHTTY, &cc, 1)) != 1) {
> } 
> } I suppose you've thought this through more than I have, but wouldn't it be
> } safer just to run traps every time the read returns?  I'm assuming a signal
> } arriving will interrupt the read in any case, so as far as I can see it's
> } pretty much equivalent in practise.
> 
> On Oct 31,  3:01pm, Sven Wischnowsky wrote:
> }
> } Unless someone knows of a system where signals don't interrupt things
> } like read.
> 
> Ever heard of BSD restartable system calls?

Yes, of course. But we set S[AV]_INTERRUPT on our signal handlers, so...

> Signals don't always interrupt things like read.  On systems that have
> the sigaction() interface, you can choose to turn restartable-ness on and
> off, but on an older BSD system the only way out of a system call from a
> signal handler is with setjmp/longjmp. 

...are there still such systems? Hm.

Anyway, the way the patch handles this should be ok, because (if I've
found all the places where a possibly blocking system call is made)
traps are called during such system calls.

> That's what I was talking about
> before in my last message.

Aha, I admit I was wondering... No, I definitely think we shouldn't
even start to think about using that as long as the way the patch
handles it works. If it works.


Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
  2000-10-31 14:01   ` Sven Wischnowsky
@ 2000-10-31 15:25     ` Bart Schaefer
  2000-10-31 15:43       ` Andrej Borsenkow
  0 siblings, 1 reply; 21+ messages in thread
From: Bart Schaefer @ 2000-10-31 15:25 UTC (permalink / raw)
  To: Zsh hackers list

On Oct 31,  1:51pm, Peter Stephenson wrote:
} Subject: Re: zsh-3.1.9-dev-6 crashes occassionally
}
} Sven wrote:
} > +	ALLOWTRAPS {
} > +	    while ((r = read(SHTTY, &cc, 1)) != 1) {
} 
} I suppose you've thought this through more than I have, but wouldn't it be
} safer just to run traps every time the read returns?  I'm assuming a signal
} arriving will interrupt the read in any case, so as far as I can see it's
} pretty much equivalent in practise.

On Oct 31,  3:01pm, Sven Wischnowsky wrote:
}
} Unless someone knows of a system where signals don't interrupt things
} like read.

Ever heard of BSD restartable system calls?

Signals don't always interrupt things like read.  On systems that have
the sigaction() interface, you can choose to turn restartable-ness on and
off, but on an older BSD system the only way out of a system call from a
signal handler is with setjmp/longjmp.  That's what I was talking about
before in my last message.  (I haven't used a modern openbsd/freebsd system,
so it may not be an issue there any longer.)

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
@ 2000-10-31 14:01   ` Sven Wischnowsky
  2000-10-31 15:25     ` Bart Schaefer
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2000-10-31 14:01 UTC (permalink / raw)
  To: zsh-workers


Peter Stephenson wrote:

> Sven wrote:
> > +	ALLOWTRAPS {
> > +	    while ((r = read(SHTTY, &cc, 1)) != 1) {
> 
> I suppose you've thought this through more than I have, but wouldn't it be
> safer just to run traps every time the read returns?  I'm assuming a signal
> arriving will interrupt the read in any case, so as far as I can see it's
> pretty much equivalent in practise.  There's nothing too nasty in the block
> underneath, but it does call zrefresh() and attachtty() which are probably
> best treated as black boxes.

Hmhm. I was about to say that traps are only insecure when they can
execute code the non-trap code currently executes, but, yes, since one 
can invoke more and more code from shell code...

Maybe I should have a second (third, fourth,...) look to see if we can 
get rid of this ALLOWTRAPS { ... } DISALLOWTRAPS stuff altogether. That 
would make me more comfortable, I think.

Unless someone knows of a system where signals don't interrupt things
like read.

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
  2000-10-31 13:19 Sven Wischnowsky
@ 2000-10-31 13:51 ` Peter Stephenson
  2000-10-31 14:01   ` Sven Wischnowsky
  0 siblings, 1 reply; 21+ messages in thread
From: Peter Stephenson @ 2000-10-31 13:51 UTC (permalink / raw)
  To: Zsh hackers list

Sven wrote:
> +	ALLOWTRAPS {
> +	    while ((r = read(SHTTY, &cc, 1)) != 1) {

I suppose you've thought this through more than I have, but wouldn't it be
safer just to run traps every time the read returns?  I'm assuming a signal
arriving will interrupt the read in any case, so as far as I can see it's
pretty much equivalent in practise.  There's nothing too nasty in the block
underneath, but it does call zrefresh() and attachtty() which are probably
best treated as black boxes.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
Cambridge Silicon Radio, Unit 300, Science Park, Milton Road,
Cambridge, CB4 0XL, UK                          Tel: +44 (0)1223 392070


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
@ 2000-10-31 13:19 Sven Wischnowsky
  2000-10-31 13:51 ` Peter Stephenson
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2000-10-31 13:19 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> ...
>  
> } We could also use a mixture: a global flag that tells the signal code
> } that it's save to invoke the trap handler right away but normally it
> } would only make them be called later. That flag could be set when zsh
> } is waiting for an external command, reading somethin or whatever.
> 
> That would probably be enough to take care of the blocking-read issue.
> However, our choice of "a safe place" to invoke the handler is still
> going to have be made with some care --

Of course.

> it has to be a place (or more
> than one) that is *guaranteed* to be reached quickly, and I just don't
> see how we can possibly enforce that when arbitrary module code may get
> involved.

We can't. Unless we want to allow immediate trap-handling in all
module code, which we don't want.


The patch below (not to be committed yet) is how far I've got.  It
makes dotrap() just put the signals of the traps to execute on a queue 
if trapsallowed is false. There are three hopefully convenient macros
to say how traps are to be executed. RUNTRAPS() makes all queued traps 
be run *now*. The pair of ALLOWTRAPS { ... } DISALOWTRAPS; should look 
familiar and can be used to temporarily allow executing traps
immediately.  These can be nested but are really only intended to be
called around short parts of the code that may block, like a read or
something like that. The last change in the interface is that dotrap() 
gets a second argument that says that the trap is to be executed
immediately (in that case any traps on the queue will be executed
before that trap).

The rest of the patch makes the macros be used in some places (inter
alia, traps are allowed to run after every command) and changes the
calls to dotrap(). I've tried the tests and they work fine.

I haven't even tried to implement the function that can be used to
block/read/write/wait everywhere (but I continue to dream about it).


Bye
 Sven

diff -u -r ../oz/Src/Zle/zle_main.c ./Src/Zle/zle_main.c
--- ../oz/Src/Zle/zle_main.c	Sun Oct 22 15:17:55 2000
+++ ./Src/Zle/zle_main.c	Mon Oct 30 20:11:38 2000
@@ -398,47 +398,49 @@
 # endif
 #endif
 	}
-	while ((r = read(SHTTY, &cc, 1)) != 1) {
-	    if (r == 0) {
-		/* The test for IGNOREEOF was added to make zsh ignore ^Ds
-		   that were typed while commands are running.  Unfortuantely
-		   this caused trouble under at least one system (SunOS 4.1).
-		   Here shells that lost their xterm (e.g. if it was killed
-		   with -9) didn't fail to read from the terminal but instead
-		   happily continued to read EOFs, so that the above read
-		   returned with 0, and, with IGNOREEOF set, this caused
-		   an infinite loop.  The simple way around this was to add
-		   the counter (icnt) so that this happens 20 times and than
-		   the shell gives up (yes, this is a bit dirty...). */
-		if (isset(IGNOREEOF) && icnt++ < 20)
-		    continue;
-		stopmsg = 1;
-		zexit(1, 0);
+	ALLOWTRAPS {
+	    while ((r = read(SHTTY, &cc, 1)) != 1) {
+		if (r == 0) {
+		    /* The test for IGNOREEOF was added to make zsh ignore ^Ds
+		       that were typed while commands are running.  Unfortuantely
+		       this caused trouble under at least one system (SunOS 4.1).
+		       Here shells that lost their xterm (e.g. if it was killed
+		       with -9) didn't fail to read from the terminal but instead
+		       happily continued to read EOFs, so that the above read
+		       returned with 0, and, with IGNOREEOF set, this caused
+		       an infinite loop.  The simple way around this was to add
+		       the counter (icnt) so that this happens 20 times and than
+		       the shell gives up (yes, this is a bit dirty...). */
+		    if (isset(IGNOREEOF) && icnt++ < 20)
+			continue;
+		    stopmsg = 1;
+		    zexit(1, 0);
+		}
+		icnt = 0;
+		if (errno == EINTR) {
+		    die = 0;
+		    if (!errflag && !retflag && !breaks)
+			continue;
+		    errflag = 0;
+		    breaks = obreaks;
+		    errno = old_errno;
+		    ALLOWTRAPS_RETURN(EOF);
+		} else if (errno == EWOULDBLOCK) {
+		    fcntl(0, F_SETFL, 0);
+		} else if (errno == EIO && !die) {
+		    ret = opts[MONITOR];
+		    opts[MONITOR] = 1;
+		    attachtty(mypgrp);
+		    zrefresh();	/* kludge! */
+		    opts[MONITOR] = ret;
+		    die = 1;
+		} else if (errno != 0) {
+		    zerr("error on TTY read: %e", NULL, errno);
+		    stopmsg = 1;
+		    zexit(1, 0);
+		}
 	    }
-	    icnt = 0;
-	    if (errno == EINTR) {
-		die = 0;
-		if (!errflag && !retflag && !breaks)
-		    continue;
-		errflag = 0;
-		breaks = obreaks;
-		errno = old_errno;
-		return EOF;
-	    } else if (errno == EWOULDBLOCK) {
-		fcntl(0, F_SETFL, 0);
-	    } else if (errno == EIO && !die) {
-		ret = opts[MONITOR];
-		opts[MONITOR] = 1;
-		attachtty(mypgrp);
-		zrefresh();	/* kludge! */
-		opts[MONITOR] = ret;
-		die = 1;
-	    } else if (errno != 0) {
-		zerr("error on TTY read: %e", NULL, errno);
-		stopmsg = 1;
-		zexit(1, 0);
-	    }
-	}
+	} DISALLOWTRAPS;
 	if (cc == '\r')		/* undo the exchange of \n and \r determined by */
 	    cc = '\n';		/* zsetterm() */
 	else if (cc == '\n')
diff -u -r ../oz/Src/builtin.c ./Src/builtin.c
--- ../oz/Src/builtin.c	Sun Oct 22 15:17:53 2000
+++ ./Src/builtin.c	Mon Oct 30 21:22:08 2000
@@ -3218,7 +3218,7 @@
 	    checkjobs();   /* check if any jobs are running/stopped */
 	if (stopmsg) {
 	    stopmsg = 2;
-	    LASTALLOC_RETURN;
+	    return;
 	}
     }
     if (in_exit++ && from_signal)
@@ -3240,7 +3240,7 @@
 	}
     }
     if (sigtrapped[SIGEXIT])
-	dotrap(SIGEXIT);
+	dotrap(SIGEXIT, 1);
     runhookdef(EXITHOOK, NULL);
     if (mypid != getpid())
 	_exit(val);
@@ -3733,6 +3733,7 @@
 zread(int izle, int *readchar)
 {
     char cc, retry = 0;
+    int ret;
 
     if (izle) {
 	int c = getkeyptr(0);
@@ -3756,7 +3757,10 @@
     }
     for (;;) {
 	/* read a character from readfd */
-	switch (read(readfd, &cc, 1)) {
+	ALLOWTRAPS {
+	    ret = read(readfd, &cc, 1);
+	} DISALLOWTRAPS;
+	switch (ret) {
 	case 1:
 	    /* return the character read */
 	    return STOUC(cc);
diff -u -r ../oz/Src/exec.c ./Src/exec.c
--- ../oz/Src/exec.c	Sun Oct 22 15:17:53 2000
+++ ./Src/exec.c	Mon Oct 30 21:22:34 2000
@@ -738,6 +738,7 @@
 execsimple(Estate state)
 {
     wordcode code = *state->pc++;
+    int lv;
 
     if (errflag)
 	return (lastval = 1);
@@ -754,9 +755,13 @@
 	    fputc('\n', xtrerr);
 	    fflush(xtrerr);
 	}
-	return (lastval = (errflag ? errflag : cmdoutval));
+	lv = (errflag ? errflag : cmdoutval);
     } else
-	return (lastval = (execfuncs[code - WC_CURSH])(state, 0));
+	lv = (execfuncs[code - WC_CURSH])(state, 0);
+
+    RUNTRAPS();
+
+    return lastval = lv;
 }
 
 /* Main routine for executing a list.                                *
@@ -887,19 +892,19 @@
 	noerrexit = oldnoerrexit;
 
 	if (sigtrapped[SIGDEBUG])
-	    dotrap(SIGDEBUG);
+	    dotrap(SIGDEBUG, 1);
 
 	/* Check whether we are suppressing traps/errexit *
 	 * (typically in init scripts) and if we haven't  *
 	 * already performed them for this sublist.       */
 	if (!noerrexit && !donetrap) {
 	    if (sigtrapped[SIGZERR] && lastval) {
-		dotrap(SIGZERR);
+		dotrap(SIGZERR, 1);
 		donetrap = 1;
 	    }
 	    if (lastval && isset(ERREXIT)) {
 		if (sigtrapped[SIGEXIT])
-		    dotrap(SIGEXIT);
+		    dotrap(SIGEXIT, 1);
 		if (mypid != getpid())
 		    _exit(lastval);
 		else
@@ -1181,9 +1186,10 @@
 	else
 	    list_pipe_text[0] = '\0';
     }
-    if (WC_PIPE_TYPE(pcode) == WC_PIPE_END)
+    if (WC_PIPE_TYPE(pcode) == WC_PIPE_END) {
 	execcmd(state, input, output, how, last1 ? 1 : 2);
-    else {
+	RUNTRAPS();
+    } else {
 	int old_list_pipe = list_pipe;
 	Wordcode next = state->pc + (*state->pc);
 	wordcode code;
@@ -1218,12 +1224,14 @@
 		entersubsh(how, 2, 0);
 		close(synch[1]);
 		execcmd(state, input, pipes[1], how, 0);
+		RUNTRAPS();
 		_exit(lastval);
 	    }
 	} else {
 	    /* otherwise just do the pipeline normally. */
 	    subsh_close = pipes[0];
 	    execcmd(state, input, pipes[1], how, 0);
+	    RUNTRAPS();
 	}
 	zclose(pipes[1]);
 	state->pc = next;
diff -u -r ../oz/Src/init.c ./Src/init.c
--- ../oz/Src/init.c	Sun Oct 22 15:17:53 2000
+++ ./Src/init.c	Mon Oct 30 21:22:47 2000
@@ -170,7 +170,7 @@
 	}
 	if (isset(SINGLECOMMAND) && toplevel) {
 	    if (sigtrapped[SIGEXIT])
-		dotrap(SIGEXIT);
+		dotrap(SIGEXIT, 1);
 	    exit(lastval);
 	}
 	if (justonce)
@@ -1101,13 +1101,19 @@
 mod_export unsigned char *
 fallback_zleread(char *lp, char *rp, int ha)
 {
+    unsigned char *ret;
     char *pptbuf;
     int pptlen;
 
     pptbuf = unmetafy(promptexpand(lp, 0, NULL, NULL), &pptlen);
     write(2, (WRITE_ARG_2_T)pptbuf, pptlen);
     free(pptbuf);
-    return (unsigned char *)shingetline();
+
+    ALLOWTRAPS {
+	ret = (unsigned char *)shingetline();
+    } DISALLOWTRAPS;
+
+    return ret;
 }
 
 /* compctl entry point pointers.  Similar to the ZLE ones. */
diff -u -r ../oz/Src/jobs.c ./Src/jobs.c
--- ../oz/Src/jobs.c	Sun Oct 22 15:17:53 2000
+++ ./Src/jobs.c	Mon Oct 30 21:23:14 2000
@@ -378,7 +378,7 @@
 	    zrefresh();
     }
     if (sigtrapped[SIGCHLD] && job != thisjob)
-	dotrap(SIGCHLD);
+	dotrap(SIGCHLD, 0);
 
     /* When MONITOR is set, the foreground process runs in a different *
      * process group from the shell, so the shell will not receive     *
@@ -389,7 +389,7 @@
 
 	if (sig == SIGINT || sig == SIGQUIT) {
 	    if (sigtrapped[sig]) {
-		dotrap(sig);
+		dotrap(sig, 0);
 		/* We keep the errflag as set or not by dotrap.
 		 * This is to fulfil the promise to carry on
 		 * with the jobs if trap returns zero.
@@ -872,15 +872,17 @@
 
     /* child_block() around this loop in case #ifndef WNOHANG */
     child_block();		/* unblocked in child_suspend() */
-    while (!errflag && (kill(pid, 0) >= 0 || errno != ESRCH)) {
-	if (first)
-	    first = 0;
-	else
-	    kill(pid, SIGCONT);
+    ALLOWTRAPS {
+	while (!errflag && (kill(pid, 0) >= 0 || errno != ESRCH)) {
+	    if (first)
+		first = 0;
+	    else
+		kill(pid, SIGCONT);
 
-	child_suspend(SIGINT);
-	child_block();
-    }
+	    child_suspend(SIGINT);
+	    child_block();
+	}
+    } DISALLOWTRAPS;
     child_unblock();
 }
 
@@ -932,9 +934,11 @@
 {
     Job jn = jobtab + thisjob;
 
-    if (jn->procs)
-	waitjob(thisjob, 0);
-    else {
+    if (jn->procs) {
+	ALLOWTRAPS {
+	    waitjob(thisjob, 0);
+	} DISALLOWTRAPS;
+    } else {
 	deletejob(jn);
 	pipestats[0] = lastval;
 	numpipestats = 1;
@@ -1270,9 +1274,11 @@
 		}
 	    return 0;
 	} else {   /* Must be BIN_WAIT, so wait for all jobs */
-	    for (job = 0; job != MAXJOB; job++)
-		if (job != thisjob && jobtab[job].stat)
-		    waitjob(job, SIGINT);
+	    ALLOWTRAPS {
+		for (job = 0; job != MAXJOB; job++)
+		    if (job != thisjob && jobtab[job].stat)
+			waitjob(job, SIGINT);
+	    } DISALLOWTRAPS;
 	    return 0;
 	}
     }
@@ -1362,8 +1368,11 @@
 		    settyinfo(jobtab[job].ty);
 		killjb(jobtab + job, SIGCONT);
 	    }
-	    if (func == BIN_WAIT)
-	        waitjob(job, SIGINT);
+	    if (func == BIN_WAIT) {
+		ALLOWTRAPS {
+		    waitjob(job, SIGINT);
+		} DISALLOWTRAPS;
+	    }
 	    if (func != BIN_BG) {
 		waitjobs();
 		retval = lastval2;
diff -u -r ../oz/Src/signals.c ./Src/signals.c
--- ../oz/Src/signals.c	Sun Oct 22 15:17:53 2000
+++ ./Src/signals.c	Mon Oct 30 21:21:55 2000
@@ -497,7 +497,7 @@
  
     case SIGHUP:
         if (sigtrapped[SIGHUP])
-            dotrap(SIGHUP);
+            dotrap(SIGHUP, 0);
         else {
             stopmsg = 1;
             zexit(SIGHUP, 1);
@@ -506,7 +506,7 @@
  
     case SIGINT:
         if (sigtrapped[SIGINT])
-            dotrap(SIGINT);
+            dotrap(SIGINT, 0);
         else {
 	    if ((isset(PRIVILEGED) || isset(RESTRICTED)) &&
 		isset(INTERACTIVE) && noerrexit < 0)
@@ -523,14 +523,14 @@
     case SIGWINCH:
         adjustwinsize(1);  /* check window size and adjust */
 	if (sigtrapped[SIGWINCH])
-	    dotrap(SIGWINCH);
+	    dotrap(SIGWINCH, 0);
         break;
 #endif
 
     case SIGALRM:
         if (sigtrapped[SIGALRM]) {
 	    int tmout;
-            dotrap(SIGALRM);
+            dotrap(SIGALRM, 0);
 
 	    if ((tmout = getiparam("TMOUT")))
 		alarm(tmout);           /* reset the alarm */
@@ -549,7 +549,7 @@
         break;
  
     default:
-        dotrap(sig);
+        dotrap(sig, 0);
         break;
     }   /* end of switch(sig) */
  
@@ -907,7 +907,9 @@
      * function will test for this, but this way we keep status flags *
      * intact without working too hard.  Special cases (e.g. calling  *
      * a trap for SIGINT after the error flag was set) are handled    *
-     * by the calling code.  (PWS 1995/06/08).			      */
+     * by the calling code.  (PWS 1995/06/08).			      *
+     *                                                                *
+     * This test is now replicated in dotrap().                       */
     if ((*sigtr & ZSIG_IGNORED) || !sigfn || errflag)
         return;
 
@@ -957,11 +959,56 @@
 	*sigtr &= ~ZSIG_IGNORED;
 }
 
-/* Standard call to execute a trap for a given signal */
+/* != 0 if trap handlers can be called immediately */
+
+/**/
+mod_export int trapsallowed;
+
+/* Queued traps and allocated length of queue. */
+
+static int *trapqueue, trapqlen;
+
+/* Number of used slots in trap queue. */
+
+/**/
+mod_export int trapqused;
+
+/* Standard call to execute a trap for a given signal.  The second
+ * argument should be zero if we may need to put the trap on the queue
+ * and 1 if it may be called immediately.  It should never be set to
+ * anything less than zero, that's used internally. */
 
 /**/
 void
-dotrap(int sig)
+dotrap(int sig, int now)
 {
-    dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
+    /* Copied from dotrapargs(). */
+    if ((sigtrapped[sig] & ZSIG_IGNORED) || !sigfuncs[sig] || errflag)
+	return;
+
+    if (now || trapsallowed) {
+	if (now < 0)
+	    RUNTRAPS();
+	dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
+    } else {
+	if (trapqlen == trapqused)
+	    trapqueue = (int *) zrealloc(trapqueue, (trapqlen += 32));
+	trapqueue[trapqused++] = sig;
+    }
+}
+
+/**/
+mod_export void
+doqueuedtraps(void)
+{
+    int sig, ota = trapsallowed;
+
+    trapsallowed = 1;
+    while (trapqused) {
+	trapqused--;
+	sig = *trapqueue;
+	memcpy(trapqueue, trapqueue + 1, trapqused * sizeof(int));
+	dotrap(sig, -1);
+    }
+    trapsallowed = ota;
 }
diff -u -r ../oz/Src/signals.h ./Src/signals.h
--- ../oz/Src/signals.h	Sun Oct 22 15:17:53 2000
+++ ./Src/signals.h	Mon Oct 30 20:06:14 2000
@@ -118,3 +118,8 @@
 extern sigset_t signal_unblock _((sigset_t));
 #endif   /* POSIX_SIGNALS */
 
+#define RUNTRAPS() do { if (trapqused) doqueuedtraps(); } while (0)
+#define ALLOWTRAPS do { RUNTRAPS(); trapsallowed++; do
+#define DISALLOWTRAPS while (0); RUNTRAPS(); trapsallowed--; } while (0)
+#define ALLOWTRAPS_RETURN(V) \
+    do { RUNTRAPS(); trapsallowed--; return (V); } while (0)
diff -u -r ../oz/Src/zsh.h ./Src/zsh.h
--- ../oz/Src/zsh.h	Sun Oct 22 15:17:54 2000
+++ ./Src/zsh.h	Mon Oct 30 19:42:27 2000
@@ -1627,8 +1627,6 @@
 #endif
 ;
 
-# define LASTALLOC_RETURN return
-
 # define NEWHEAPS(h)    do { Heap _switch_oldheaps = h = new_heaps(); do
 # define OLDHEAPS       while (0); old_heaps(_switch_oldheaps); } while (0);
 

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
@ 2000-10-30 10:25 Sven Wischnowsky
  0 siblings, 0 replies; 21+ messages in thread
From: Sven Wischnowsky @ 2000-10-30 10:25 UTC (permalink / raw)
  To: zsh-workers


Thomas Koehler wrote:

> ...
> 
> Ugh.

Yes.

> Would it help if I'd change my signal handler not to use local
> parameters?

It might make it occur less often, but it could probably still happen
if a completion function uses a parameter with the same name as one of 
yours (`x' might be used somewhere).

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
@ 2000-10-24  7:53 Sven Wischnowsky
  0 siblings, 0 replies; 21+ messages in thread
From: Sven Wischnowsky @ 2000-10-24  7:53 UTC (permalink / raw)
  To: zsh-workers


Thomas Koehler wrote:

> ...
> 
> > > #0  0x401011cb in free () from /lib/libc.so.6
> > > (gdb) bt
> > > #0  0x401011cb in free () from /lib/libc.so.6
> > > #1  0x40101053 in free () from /lib/libc.so.6
> > > #2  0x807613e in zsfree ()
> > > #3  0x80925e3 in freearray ()
> > > #4  0x807cd66 in arrsetfn ()
> > > #5  0x807cc82 in stdunsetfn ()
> > > #6  0x807cb5a in unsetparam_pm ()
> > > #7  0x807de6d in endparamscope ()
> > > #8  0x8065a49 in scanhashtable ()
> > > #9  0x807dd8f in endparamscope ()
> > > #10 0x8060304 in runshfunc ()
> > > #11 0x4021f682 in comp_setunset () from /usr/lib/zsh/3.1.9-dev-6/zsh/co=
> mple=3D
> > > te.so
> >=20
> > Hm. This seems to suggest that there is some trouble with unsetting
> > the special completion parameters. $words, I guess. We already fixed
> > some problems with it some time ago, but that was before 3.1.9.
> >=20
> > I'll try to stare some more at the code, but can't promise anything.

After looking again: no this is probably not $words, but a normal
array (otherwise it would have called compunsetfn()).

But the whole stack trace shows that his zsh is heavily optimised
(comp_setunset() doesn't call runshfunc()), so this is little or no
help at all.

This is almost certainly a memory corruption problem, something is
writing into memory allocated for a parameter and when that parameter
is freed...

> Could my whole .zshrc be of any help?
> ~> wc -l .zshrc
>     625 .zshrc

Dunno, you can send it to me and I'll give it a try, but I don't know
when I'll find the time.


Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
  2000-10-23 13:04 Sven Wischnowsky
@ 2000-10-23 15:12 ` Thomas Köhler
  0 siblings, 0 replies; 21+ messages in thread
From: Thomas Köhler @ 2000-10-23 15:12 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 1879 bytes --]

On Mon, Oct 23, 2000 at 03:04:00PM +0200,
Sven Wischnowsky <wischnow@informatik.hu-berlin.de> wrote:
> 
> Thomas Koehler wrote:
> 
> > ...
> >
> > #0  0x401011cb in free () from /lib/libc.so.6
> > (gdb) bt
> > #0  0x401011cb in free () from /lib/libc.so.6
> > #1  0x40101053 in free () from /lib/libc.so.6
> > #2  0x807613e in zsfree ()
> > #3  0x80925e3 in freearray ()
> > #4  0x807cd66 in arrsetfn ()
> > #5  0x807cc82 in stdunsetfn ()
> > #6  0x807cb5a in unsetparam_pm ()
> > #7  0x807de6d in endparamscope ()
> > #8  0x8065a49 in scanhashtable ()
> > #9  0x807dd8f in endparamscope ()
> > #10 0x8060304 in runshfunc ()
> > #11 0x4021f682 in comp_setunset () from /usr/lib/zsh/3.1.9-dev-6/zsh/comple=
> > te.so
> 
> Hm. This seems to suggest that there is some trouble with unsetting
> the special completion parameters. $words, I guess. We already fixed
> some problems with it some time ago, but that was before 3.1.9.
> 
> I'll try to stare some more at the code, but can't promise anything.

Could my whole .zshrc be of any help?
~> wc -l .zshrc
    625 .zshrc

Perhaps it's only triggered by one of my settings?

> Do you have any remembrance of what you tried to complete when it crashed?

Well, as zsh dumped core in /scratch2/mp3 while completing, it was
either "cd" completing directory names or "mpg123" completing file and
directory names, can't say for sure now.

But I think zsh also crashed for other things (hostname completion for
ssh or something)... Can't really say for sure at the moment.

> Bye
>  Sven

CU,
Thomas

-- 
 Thomas Köhler Email:   jean-luc@picard.franken.de     | LCARS - Linux
     <><        WWW:     http://jeanluc-picard.de      | for Computers
                IRC:             jeanluc               | on All Real
               PGP public key available from Homepage! | Starships

[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: zsh-3.1.9-dev-6 crashes occassionally
@ 2000-10-23 13:04 Sven Wischnowsky
  2000-10-23 15:12 ` Thomas Köhler
  0 siblings, 1 reply; 21+ messages in thread
From: Sven Wischnowsky @ 2000-10-23 13:04 UTC (permalink / raw)
  To: zsh-workers


Thomas Koehler wrote:

> ...
>
> #0  0x401011cb in free () from /lib/libc.so.6
> (gdb) bt
> #0  0x401011cb in free () from /lib/libc.so.6
> #1  0x40101053 in free () from /lib/libc.so.6
> #2  0x807613e in zsfree ()
> #3  0x80925e3 in freearray ()
> #4  0x807cd66 in arrsetfn ()
> #5  0x807cc82 in stdunsetfn ()
> #6  0x807cb5a in unsetparam_pm ()
> #7  0x807de6d in endparamscope ()
> #8  0x8065a49 in scanhashtable ()
> #9  0x807dd8f in endparamscope ()
> #10 0x8060304 in runshfunc ()
> #11 0x4021f682 in comp_setunset () from /usr/lib/zsh/3.1.9-dev-6/zsh/comple=
> te.so

Hm. This seems to suggest that there is some trouble with unsetting
the special completion parameters. $words, I guess. We already fixed
some problems with it some time ago, but that was before 3.1.9.

I'll try to stare some more at the code, but can't promise anything.

Do you have any remembrance of what you tried to complete when it crashed?

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 21+ messages in thread

* zsh-3.1.9-dev-6 crashes occassionally
@ 2000-10-21 12:34 Thomas Köhler
  0 siblings, 0 replies; 21+ messages in thread
From: Thomas Köhler @ 2000-10-21 12:34 UTC (permalink / raw)
  To: ZSH workers mailing list

[-- Attachment #1: Type: text/plain, Size: 7616 bytes --]

Hi there,
I have the following problem with zsh-3.1.9-dev-6 on Debian GNU/Linux
for i386:
Sometimes, while trying to complete, zsh crashes and dumps core. In
fact, the problem has been there for quite a while now, perhaps it has
been there since the new completions system has been introduced - I
don't know. The problem is: I can't reproduce the bug. It just happens
to occur every once in a while.
Well, this is not the only problem: Sometimes, zsh forgets its
completion settings. I use this line in my .zshrc:
zstyle ':completion:*' completer _complete _ignored _match _correct _approximate _prefix
Now, sometimes, for some strange reason, zsh forgets to complete on tab
and starts to _correct things right away: For example, I had a directory
"abcdef" and a directory "abx" and typed "cd abc<TAB>" which resulted in
"cd abx".

Why do I report both things in one mail? Because I guess there might be
a problem in that "function calls function calls function"-way of doing
things: perhaps there's some functions that use a global variable by
accident instead of a local one, resulting in ill side-effects or such?

I use Debian's zsh-package (the one in woody aka unstable), but the
problem also occurs with self-compiled zsh (so it doesn't seem to be
specific to Debian's compiled version anyways).

Well... here's a gdb backtrace of a zsh core dump:

/scratch2/mp3> gdb =zsh core 
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...(no debugging symbols found)...
Core was generated by `zsh'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/libnsl.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/libnsl.so.1
Reading symbols from /lib/libncurses.so.5...(no debugging symbols found)...done.
Loaded symbols for /lib/libncurses.so.5
Reading symbols from /lib/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /lib/libnss_compat.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/libnss_compat.so.2
Reading symbols from /usr/lib/zsh/3.1.9-dev-6/zsh/zle.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/zsh/3.1.9-dev-6/zsh/zle.so
Reading symbols from /usr/lib/zsh/3.1.9-dev-6/zsh/parameter.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/zsh/3.1.9-dev-6/zsh/parameter.so
Reading symbols from /usr/lib/zsh/3.1.9-dev-6/zsh/rlimits.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/zsh/3.1.9-dev-6/zsh/rlimits.so
Reading symbols from /usr/lib/zsh/3.1.9-dev-6/zsh/complete.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/zsh/3.1.9-dev-6/zsh/complete.so
Reading symbols from /usr/lib/zsh/3.1.9-dev-6/zsh/zutil.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/zsh/3.1.9-dev-6/zsh/zutil.so
Reading symbols from /usr/lib/zsh/3.1.9-dev-6/zsh/complist.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/zsh/3.1.9-dev-6/zsh/complist.so
Reading symbols from /usr/lib/zsh/3.1.9-dev-6/zsh/computil.so...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/zsh/3.1.9-dev-6/zsh/computil.so
#0  0x401011cb in free () from /lib/libc.so.6
(gdb) bt
#0  0x401011cb in free () from /lib/libc.so.6
#1  0x40101053 in free () from /lib/libc.so.6
#2  0x807613e in zsfree ()
#3  0x80925e3 in freearray ()
#4  0x807cd66 in arrsetfn ()
#5  0x807cc82 in stdunsetfn ()
#6  0x807cb5a in unsetparam_pm ()
#7  0x807de6d in endparamscope ()
#8  0x8065a49 in scanhashtable ()
#9  0x807dd8f in endparamscope ()
#10 0x8060304 in runshfunc ()
#11 0x4021f682 in comp_setunset () from /usr/lib/zsh/3.1.9-dev-6/zsh/complete.so
#12 0x80602aa in runshfunc ()
#13 0x806013c in doshfunc ()
#14 0x805fc67 in getproc ()
#15 0x805e16c in execsubst ()
#16 0x805bc15 in execlist ()
#17 0x805b3f3 in execlist ()
#18 0x805af9b in execlist ()
#19 0x8073768 in execif ()
#20 0x805dfef in execsubst ()
#21 0x805bc15 in execlist ()
#22 0x805b3f3 in execlist ()
#23 0x805af71 in execlist ()
#24 0x805ad46 in execode ()
#25 0x80602f0 in runshfunc ()
#26 0x4021f682 in comp_setunset () from /usr/lib/zsh/3.1.9-dev-6/zsh/complete.so
#27 0x80602aa in runshfunc ()
#28 0x806013c in doshfunc ()
#29 0x805fc67 in getproc ()
#30 0x805e16c in execsubst ()
#31 0x805bc15 in execlist ()
#32 0x805b3f3 in execlist ()
#33 0x805af9b in execlist ()
#34 0x8073768 in execif ()
#35 0x805dfef in execsubst ()
#36 0x805bc15 in execlist ()
#37 0x805b3f3 in execlist ()
#38 0x805af71 in execlist ()
#39 0x805ad46 in execode ()
#40 0x80602f0 in runshfunc ()
#41 0x4021f682 in comp_setunset () from /usr/lib/zsh/3.1.9-dev-6/zsh/complete.so
#42 0x80602aa in runshfunc ()
#43 0x806013c in doshfunc ()
#44 0x805fc67 in getproc ()
#45 0x805e16c in execsubst ()
#46 0x805bc15 in execlist ()
#47 0x805b3f3 in execlist ()
#48 0x805af71 in execlist ()
#49 0x80736b1 in execif ()
#50 0x805dfef in execsubst ()
#51 0x805bc15 in execlist ()
#52 0x805b3f3 in execlist ()
#53 0x805af71 in execlist ()
#54 0x8072bfe in execfor ()
#55 0x805dfef in execsubst ()
#56 0x805bc15 in execlist ()
#57 0x805b3f3 in execlist ()
#58 0x805af71 in execlist ()
#59 0x8072bfe in execfor ()
#60 0x805dfef in execsubst ()
#61 0x805bc15 in execlist ()
#62 0x805b3f3 in execlist ()
#63 0x805af71 in execlist ()
#64 0x805ad46 in execode ()
#65 0x80602f0 in runshfunc ()
#66 0x4021f682 in comp_setunset () from /usr/lib/zsh/3.1.9-dev-6/zsh/complete.so
#67 0x80602aa in runshfunc ()
#68 0x806013c in doshfunc ()
#69 0x40221627 in after_complete () from /usr/lib/zsh/3.1.9-dev-6/zsh/complete.so
#70 0x40221d61 in after_complete () from /usr/lib/zsh/3.1.9-dev-6/zsh/complete.so
#71 0x402202b6 in do_completion () from /usr/lib/zsh/3.1.9-dev-6/zsh/complete.so
#72 0x80784a1 in runhookdef ()
#73 0x401deb4b in inststrlen () from /usr/lib/zsh/3.1.9-dev-6/zsh/zle.so
#74 0x401dc55c in parambeg () from /usr/lib/zsh/3.1.9-dev-6/zsh/zle.so
#75 0x401db64b in expandorcomplete () from /usr/lib/zsh/3.1.9-dev-6/zsh/zle.so
#76 0x401db282 in completecall () from /usr/lib/zsh/3.1.9-dev-6/zsh/zle.so
#77 0x401d34b8 in execzlefunc () from /usr/lib/zsh/3.1.9-dev-6/zsh/zle.so
#78 0x401d30f1 in zleread () from /usr/lib/zsh/3.1.9-dev-6/zsh/zle.so
#79 0x806ca95 in ingetc ()
#80 0x806c9c6 in ingetc ()
#81 0x8066f00 in iaddtoline ()
#82 0x8070407 in gettok ()
#83 0x806fe45 in yylex ()
#84 0x807e6d1 in parse_event ()
#85 0x806a63d in loop ()
#86 0x806c744 in zsh_main ()
#87 0x80515d8 in main ()
#88 0x400adbcc in __libc_start_main () from /lib/libc.so.6
(gdb) 

CU,
Thomas

-- 
 Thomas Köhler Email:   jean-luc@picard.franken.de     | LCARS - Linux
     <><        WWW:     http://jeanluc-picard.de      | for Computers
                IRC:             jeanluc               | on All Real
               PGP public key available from Homepage! | Starships

[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2000-11-08 10:54 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-10-30  8:32 zsh-3.1.9-dev-6 crashes occassionally Sven Wischnowsky
2000-10-30  9:56 ` Peter Stephenson
2000-10-30 10:10 ` Thomas Köhler
2000-10-30 16:18 ` Bart Schaefer
  -- strict thread matches above, loose matches on Subject: below --
2000-11-08 10:54 Sven Wischnowsky
2000-11-08  9:41 Sven Wischnowsky
2000-11-08 10:33 ` Thomas Köhler
2000-11-01  9:41 Sven Wischnowsky
2000-11-03 15:42 ` Bart Schaefer
2000-11-05 17:55   ` Thomas Köhler
2000-10-31 15:42 Sven Wischnowsky
2000-10-31 13:19 Sven Wischnowsky
2000-10-31 13:51 ` Peter Stephenson
2000-10-31 14:01   ` Sven Wischnowsky
2000-10-31 15:25     ` Bart Schaefer
2000-10-31 15:43       ` Andrej Borsenkow
2000-10-30 10:25 Sven Wischnowsky
2000-10-24  7:53 Sven Wischnowsky
2000-10-23 13:04 Sven Wischnowsky
2000-10-23 15:12 ` Thomas Köhler
2000-10-21 12:34 Thomas Köhler

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).