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 ?

----

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

Reply via email to