[comp.unix.wizards] driver close from exit can't catch signal?

steve@nuchat.UUCP (Steve Nuchia) (07/29/90)

Working on a driver recently I needed to sleep waiting for
a pending transaction completion interupt in the close routine.
Since the interupt wasn't guaranteed to come, I wanted to
be able to catch a signal.  I found that it works when the
user calls close directly but not when close is called from exit.

I thought the observation might be due to the signal causing
the close routine to be reentered, but a quick printf showed
that was not the case.  The wakeup just isn't happening.

So, I got rid of the sleep, cancelling the pending operation.
Lucky the situation was one where that was acceptable.

This is in a SysV thing.  Is this normal and expected?  I couldn't
find anything about it in the AT+T driver books.
-- 
Steve Nuchia	      South Coast Computing Services      (713) 964-2462
"To learn which questions are unanswerable, and _not_to_answer_them;
this skill is most needful in times of stress and darkness."
		Ursula LeGuin, _The_Left_Hand_of_Darkness_

buck@siswat.UUCP (A. Lester Buck) (07/30/90)

In article <26789@nuchat.UUCP>, steve@nuchat.UUCP (Steve Nuchia) writes:
> Working on a driver recently I needed to sleep waiting for
> a pending transaction completion interupt in the close routine.
> Since the interupt wasn't guaranteed to come, I wanted to
> be able to catch a signal.  I found that it works when the
> user calls close directly but not when close is called from exit.

Since we all know that, unfortunately, interrupts are never guaranteed to
come, the only thing to do in an industrial strength driver is have a
watchdog timer.  At some reasonable interval (every 1-10 sec, maybe) it
wakes up and checks hardware registers and driver state variables to see if
it should be receiving an interrupt.  It then possibly has to go back to
sleep for one more time period - if no interrupt has been received then, it
does whatever hardware reset is necessary to get things flowing again.

> This is in a SysV thing.  Is this normal and expected?  I couldn't
> find anything about it in the AT+T driver books.

The exit() system calls I have seen atomicly mask all signals at the
beginning, then quite a while later close all files.  There isn't much to be
done with signals anyway, because once exit() is entered, a process never
gets back to user mode, and signal frames (fake calls to signal handlers)
are built on the user's stack, to be executed as he is returning to user
mode.

The standard way to grab signals in a driver is by sleeping with PCATCH
or'ed into the sleep priority.  Then wakeup has sleep return one instead of
zero, and the driver is expected to perform a longjmp(u.u_qsav) when it has
cleaned up whatever (canceling outstanding timers, etc.).  The driver might
even save the u.u_qsav and replace it with it's own jmpbuf to catch a signal
directly (wakeup does the longjmp itself if PCATCH is not set), but that is
probably not recommended.

The PCATCH/u_qsav information is in the AT&T Driver Development Manual,
the excellent manual in a three ring binder.  I paid $100 last year, but
I think it is $200 now.

-- 
A. Lester Buck     buck@siswat.lonestar.org  ...!texbell!moray!siswat!buck

steve@nuchat.UUCP (Steve Nuchia) (07/30/90)

In article <544@siswat.UUCP> buck@siswat.UUCP (A. Lester Buck) writes:
>Since we all know that, unfortunately, interrupts are never guaranteed to
>come, the only thing to do in an industrial strength driver is have a
>watchdog timer.  At some reasonable interval (every 1-10 sec, maybe) it

Which brings up another problem -- there does not appear to be a good
way to have a watchdog call the interrupt routine if the priority level
of the ISR isn't the same as the one timeout uses.  The "excellent manual"
doesn't even say what priority level you get called at out of timeout.
(At least not that I can find now.  I thought I had seen it once but I
gave up after hunting for it for a couple of hours last week.)

Best way I could figure was to use a couple of gate-guard flags.  Yuck.
There has to be a canonical way to do this, right?

This device does need a watchdog, but I've been holding off putting
it in so as to get some idea how frequently it loses interupts.  Also
hoping for inspiration on the above problem.

>The standard way to grab signals in a driver is by sleeping with PCATCH
>or'ed into the sleep priority.  Then wakeup has sleep return one instead of

I about half expected this to work even inside exit, but Noooo.

>even save the u.u_qsav and replace it with it's own jmpbuf to catch a signal
>directly (wakeup does the longjmp itself if PCATCH is not set), but that is
>probably not recommended.

Not now that PCATCH extists.  My understanding is that saving u_qsav
used to be The Way.

>The PCATCH/u_qsav information is in the AT&T Driver Development Manual,
>the excellent manual in a three ring binder.  I paid $100 last year, but
>I think it is $200 now.

I do sincerely hope "excellent" is simply missing a smiley.  I've been
wearing out my client's copy, and it is infuriating.  Aside from about
one trivial copy-editing botch per page, it has a very low information
density, the customary (for AT+T) nonsensical organization, and it just
leaves out a whole lot of necessary information.
-- 
Steve Nuchia	      South Coast Computing Services      (713) 964-2462
"To learn which questions are unanswerable, and _not_to_answer_them;
this skill is most needful in times of stress and darkness."
		Ursula LeGuin, _The_Left_Hand_of_Darkness_

mb@ttidca.TTI.COM (Michael Bloom) (07/31/90)

In article <26789@nuchat.UUCP> steve@nuchat.UUCP (Steve Nuchia) writes:

>Since the interupt wasn't guaranteed to come, I wanted to
>be able to catch a signal.  I found that it works when the
>user calls close directly but not when close is called from exit.

>This is in a SysV thing.  Is this normal and expected?  I couldn't
>find anything about it in the AT+T driver books.

Yes. If you run /etc/crash while your driver is blocked in a close
called from exit, you'll see that all signals have been set to
SIG_IGN.

I dealt with a problem somewhat like yours once with a test of the
form "(u.u_signal[SIGKILL -1] == SIG_IGN)", which should only be true
in your close routine if it is called from exit. I didn't really like
it, but it did the job.

bruner@sp15.csrd.uiuc.edu (John Bruner) (07/31/90)

In article <18901@ttidca.TTI.COM>, mb@ttidca (Michael Bloom) writes:
>I dealt with a problem somewhat like yours once with a test of the
>form "(u.u_signal[SIGKILL -1] == SIG_IGN)", which should only be true
>in your close routine if it is called from exit. I didn't really like
>it, but it did the job.

On (at least some) BSD systems, u.u_signal[SIGKILL-1] == SIG_IGN for
processes 1 and 2.  You can't ignore kill signals, but the kernel
initializes them this way when it spawns "init" and the pageout
daemon.  It seems unlikely that either of these will call a device's
close routine; however, beware of using this technique in other
situations.
--
John Bruner	Center for Supercomputing R&D, University of Illinois
	bruner@csrd.uiuc.edu		(217) 244-4476	

chris@mimsy.umd.edu (Chris Torek) (08/02/90)

In article <544@siswat.UUCP> buck@siswat.UUCP (A. Lester Buck) writes:
>Since we all know that, unfortunately, interrupts are never guaranteed to
>come, the only thing to do in an industrial strength driver is have a
>watchdog timer.

(I left this in because it bears repeating.  `Expect hardware to malfunction.')

>The standard way to grab signals in a driver is by sleeping with PCATCH
>or'ed into the sleep priority.  Then wakeup has sleep return one instead of
>zero, and the driver is expected to perform a longjmp(u.u_qsav) when it has
>cleaned up whatever (canceling outstanding timers, etc.).

Note that things are quite different in Berkeley Unix.

In 4.[123]BSD and derivatives sleep() either returns normally (after a
wakeup()) or does not return at all (via longjmp).  In 4.3-Reno, and
thus eventually in 4.4BSD, sleep does take a PCATCH flag, but:

	a. the routine is called tsleep(); it has four parameters, and
	b. one of these is a timeout (in clock ticks);
	c. tsleep returns an error number from "errno.h", which is
	   either 0, EWOULDBLOCK, ERESTART, or EINTR.

ERESTART is a `special' internal error code that causes a system
call to be restarted (on the VAX and Tahoe, by backing up the PC
so that the call is redone).  tsleep returns EWOULDBLOCK if the
timeout expires before a wakeup() occurs.  It returns ERESTART or
EINTR only if the PCATCH flag is set and a signal occurs; in this
case, which is chosen depends on whether the SA_RESTART bit is set
in the signal action (this is a POSIX thingie).

In particular, setjmp and longjmp are both gone in 4.3BSD-Reno.
(setexit and reset are still there, if you compile in the kernel
debugger.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris