On Mon, Mar 18, 2013 at 2:31 AM, Roland Mainz <[email protected]> wrote: > On Mon, Mar 11, 2013 at 7:39 PM, David Korn <[email protected]> wrote: >> cc: [email protected] [email protected] >> Subject: Re: Signal trap loop behaviour... >> -------- >> >>> While doing some tests with ast-ksh.2013-02-22 I noticed an odd >>> behaviour with signal traps: >>> The following example should (in theory) run in an endless loop... but >>> ast-ksh.2013-02-22 prints only one iteration and then quits: >>> -- snip -- >>> $ ~/bin/ksh -c 'trap "echo blabla ; kill -RTMIN $$ ; true" RTMIN ; >>> kill -RTMIN $$ ; true ; echo done' >>> blabla >>> done >>> -- snip -- >>> >>> Why does that happen ? Both bash and dash print multiple lines with >>> "blabla" ... either until the stack is exhausted (leading to a >>> SIGSEGV/SIGBUS) or an internal limit is eached... and AFAIK ksh93 >>> should allow endless loops, too... but without crashing or having >>> issues with internal limits. >>> >>> Would it be standard-conforming to change the behaviour to save a >>> signal (and siginfo data) while a trap for the same signal number and >>> execute the trap again for each entry in that list ? That would allow >>> that traps are executed as expected but without recursing deeper and >>> deeper into the stack until it is exhausted (alternatively... if this >>> is not conforming behaviour... it may be nice to offer an option for >>> this signal-deferring-until-trap-is-done behaviour) ... >> >> The way I read the standard, there is no reason for a shell to run >> out of stack space. >> >> In section 2.11, Signals and Error Handling, paragraph 2 states, >> "When a signal for which a trap has been set is received, while the >> shell is waiting for a foreground command, the trape associated with that >> signal shall not be executed until after the foreground comand >> has completed." >> >> In your example, the foreground command is >> kill -RTMIN $$ >> and this command must complete. Similarily, the trap command must be >> complete before 'kill -RTMIN $$' from within the trap can begin >> to execute so that stack would not have grown. >> >> In ksh, I disable the signal corresponding to the signal I am >> processing (the way C does) when I run a trap on the signal so it >> only executes once. >> >> This avoids an infinite loop. > > Ok... but if I understand the standard correctly it says "the trape > associated with that signal shall not be executed until after the > foreground comand has completed" but _not_ throw that trap completely > away like the current ksh93 implementation appears (erm... I only > followed the code path for passing the siginfo data around... it seems > they are stored in an array indexed by signal number... but what > happens if multiple signals of the same type arrive with high > frequency ? It seems the older, unprocessed siginfo data are > overwritten by the newer siginfo data) to do. Currently if signals > arrive in very high frequency then some of them get "lost", making > signals unreliable. > Given that signals have "payloads" (like the realtime signals have by > default (the value/address field) and all Unix/Linux > derivates/implementations which implement siginfo) this doesn't sound > like a good idea. > > After some thinking... would the following algorithm work: > 1. All incoming signals for which traps are registered (or otherwise > used by the shell (like SIGCHLD)), including SIGCHLD, SIGRT* and > SIGALARM a single trap function is used which records the signal in a > linked list (e.g. FIFO order) by allocating a matching structure, > filling it and then appending it to the end of the list. The function > then immediately returns to the caller (|sh_setsiginfo()|+|sh_trap()| > are NOT called at this point) > 2. When the next shell command is ready the list is checked and all > pending entries in the list are processed in fifo order... including > calling |sh_setsiginfo()|+|sh_trap()| etc. > > The advantage of this split is AFAIK that most of the complexities of > the current implementation are avoided (including that special > handling of SIGCHLD and SIGALRM is AFAIK not required) and that > .sh.sig.* works reliable (and in the example above it allows enless > loops in a shell created by sending signals to itself (as long as new > signals are send) without triggering a quick stack exhaustion). > > Example (for loosing some SIGRTMIN signals): > -- snip -- > $ ksh -c 'compound -a ar ; trap "ar+=( value=\${.sh.sig.value} > pid=\${.sh.sig.pid} )" RTMIN ; integer thispid=$$ ; for ((i=0 ; i < > 512 ; i++ )) ; do kill -q $i -RTMIN $thispid & ; done ; while ! wait > ; do true ; done ; print "wait=$?" ; printf "%s\n" "${#ar[@]}" ; print > done' > wait=0 > 166 > done > -- snip -- > AFAIK this example should print $'512\ndone\n' but right now it prints > random numbers from 1-512 followed by 'done' ... the reason seems to > be that the |shp->siginfo[SIGCHLD]| data are overwritten... > ... or am I reading the code the wrong way ?
BTW: I forgot to explain why I suggested a single-linked list as FIFO queue... the idea is to _not_ disable signals when the siginfo is processed in the signal callback... instead signals can be received even while the signal callback is processed... this is safe as long the insertion into the single-linked list is done using atomic instructions ([1]). [1]=Erm... Glenn: (Without digging around) Does ASO have a compare-and-swap for pointers ? ---- Bye, Roland -- __ . . __ (o.\ \/ /.o) [email protected] \__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer /O /==\ O\ TEL +49 641 3992797 (;O/ \/ \O;) _______________________________________________ ast-developers mailing list [email protected] http://lists.research.att.com/mailman/listinfo/ast-developers
