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

Re: PATCH: Re: Allowing traps



On Nov 23,  9:11am, Sven Wischnowsky wrote:
} 
} Bart Schaefer wrote:
} > This is what it comes down to:  The problem only occurs with signals that
} > can arrive asynchronously.  We already have the signal queueing code to
} > handle that case; if it needs to be applied more widely, we should do that
} 
} Of course I have no objections to use a cleaner solution, but will the 
} signal-blocking really allow us to execute more trap handlers
} immediately?

The signal queueing mechanism doesn't actually block the signals, it just
adds them to a queue which is processed later.  It never grows the array
used for the queue and it maintains the front and rear as pointers so it
can cycle; thus it never has to realloc() or memcpy(), both of which are
unsafe.

On the other hand, it assumes signals are only queued briefly, so that it
would be extremely unlikely for a large number of them to arrive at once.
You could probably overwhelm it by deliberately bombarding zsh with a lot
of different signals in a tight loop.  We should increase the queue size
if we start using it a lot more widely.

} Considering the many places where concurrent execution is unsafe...

Well, that's a design flaw that we should be addressing, even if only
gradually, rather than something we sweep under the rug by making some
other part of the execution incorrect.

} And who is going to find all the places where we have to block/unblock 
} signals? (To keep the sections with signals blocked short.)

We could start by wrapping every function in mem.c with queue_signals()/
unqueue_signals().  That'd probably take care of a lot of the problems.

} Somehow I envision many extra system calls

The signal queueing mechanism only makes system calls if a signal actually
gets queued; then it emulates the signal masking that the OS would set up
during the signal handler call, when it finally does call the handler.

We only need to block signals when OS-level side-effects [such as read()
giving EINTR] must be prevented.

} but I really haven't tried to make a list where we need to keep trap
} handlers from running, so I may be wrong...

The short answer would be "everywhere that we manipulate global variables
that are pointers."  That's a bit strong, as simple dereferencing should
be OK.  Based on a grep of *.(c|h|e#pro) files, there appear to be at least
234 such variables (including structs that may contain pointers, though I
may have missed some of those), of which 44 are static and 57 are part of
the completion system.  Another 35 are part of ZLE.

So 25% of the global pointers are in the completion system, and I'd be
willing to bet that it modifies its globals a lot more heavily than just
about anything except the memory allocators.  That makes the completion
system an awfully large target for an interactive shell that's receiving
SIGALRM once every second; no wonder Thomas is seeing problems.

The other pesky bits are the parameter tables, which could mostly be
covered by doctoring params.c.

-- 
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   



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