Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Jul 1998 23:57:38 +0000 (GMT)
From:      Terry Lambert <tlambert@primenet.com>
To:        Don.Lewis@tsc.tdk.com (Don Lewis)
Cc:        tlambert@primenet.com, Don.Lewis@tsc.tdk.com, freebsd-hackers@FreeBSD.ORG
Subject:   Re: Code Logic Question in 2.2 RELENG
Message-ID:  <199807012357.QAA27776@usr07.primenet.com>
In-Reply-To: <199807011017.DAA05610@salsa.gv.tsc.tdk.com> from "Don Lewis" at Jul 1, 98 03:17:06 am

next in thread | previous in thread | raw e-mail | index | archive | help
> The original signal() implementation reset the handler to SIG_DFL before
> calling the handler, which generally required you to rearm the handler
> from within the handler.  System V kept this behaviour and BSD changed
> it to something more sane but incompatible.  Some implementations can
> do bad things if you rearm the handler from within the handler.  I think
> the problem is if you rearm the SIGCLD/SIGCHLD handler before reaping
> any waiting processes, the handler gets re-entered.

Yes.  Signals are persistent conditions.

Arming a handler in a handler is generally bad practice, anyway, due to
the obvious race conditions.  Even if you do it as absolutely the
last thing, there is a tiny involuntary preeemption window before the
ret is executed that could cause you to reenter on the same signal stack.

SystemV was technically wrong.

The SIGCLD/SIGCHLD behaviour is also technically pilot error; the
correct method of handling this (because of the possibility of
signal stacking, is to set a flag in the handler and do the reaping
in the main loop of the program after the flag is noted as having
been set.

> } > Ick!  If you leave out a setjmp(), you'll return to the wrong place.
> } 
> } And if I call memcpy with arguments in bcopy order, I'll get the
> } wrong results, too.
> } 
> } Bad input == bad output.  I don't see your objection.
> 
> I think this makes the code harder to maintain.  If you add a new blocking
> syscall and forget the setjmp(), you'll intermittently return to the
> wrong place in the code, which will be difficult to debug.  Forgetting
> to catch EINTR is easier to track down, especially if you are careful
> to check return values and errno.

Depends.  If the code is a call-conversion user space threads
implementation, it makes it a hell of a lot easier, since the calls
are restarted, and you don't partially abort a wrappered system call
in a library routine.  For example, with an fd lock set, but never
cleared.

Library routines that implement virtual system calls, which is most
of them (except where idiot standards writers didn't want to dictate
[correct] implementation in the face of existing [incorrect] vendor
implementation), want to restart after a flag is set in the handler
to indicate one or more events of that type have taken place.


> } > This also prevents you from keeping variables in registers, because
> } > they won't be restored when you return.
> } 
> } What system are you running?  Man setjmp(3) says:
> } 
> } 	All accessible objects have values as of the time longjmp()
> } 	routine was called, except that the values of objects of
> } 	automatic storage invocation duration that do not have the
> } 	volatile type and have been changed between the setjmp()
> } 	invocation and longjmp() call are indeterminate.
> 
> This is what I'm referring to.  I just love indeterminate code ...

This indeterminism was brought to you by the ANSI C X3J11 committee,
who in their infinite wisdom, decided that a compiler should be able
to make some bogus assumptions except where you explicitly tell it
it shouldn't through the use of the "volatile" keyword to indicate
a non-procedural data flow context escape may affect the variables
value.

This is one of the reasons I hate the ANSI C specification: you
must use a keyword that didn't exist in your old code to make
your old code run like it used to instead of malfunctioning.

The short answer is "declare the variables 'volatile', and the
compiler won't make the bogus assumptions about them".

The long answer involves why "volatile" should be a function attribute
instead of a variable attribute, and that external variable referenced
by a function should taint the variable (the ANSI C "volatile" semantic)
and the issue be resolved by a smarter linker, and code generation
delayed intil inter-object dependencies of this type can be resolved.


> % uname -rs
> HP-UX B.10.20
> 
> The fine man page sez:
> 
>                 Before calling the signal-catching handler, the system
>                 signal action of sig is set to SIG_HOLD.  During a normal
>                 return from the signal-catching handler, the system signal
>                 action is restored to func and any held signal of this type
>                 is released. If a non-local goto (longjmp(3C)) is taken,
>                 sigrelse() must be called to restore the system signal
>                 action to func and release any held signal of this type.
>  
> though on careful reading this applies to sigset(), while signal() just
> sets the action back to SIG_DFL.

Yes.  This is rather bogus; the longjmp semantics are known to
push the signal out of scope; the stack transition is easily knowable
to the longjmp code, which must unwind the stack.  This is a lazy
lomgjmp implementation.


					Terry Lambert
					terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199807012357.QAA27776>