Allow CK to terminate on FreeBSD

Remco Treffkorn remco at rvt.com
Tue Sep 4 21:42:53 PDT 2007


On Tuesday 04 September 2007, Joe Marcus Clarke wrote:
> On Tue, 2007-09-04 at 14:24 -0700, Remco Treffkorn wrote:
> > On Friday 31 August 2007, Joe Marcus Clarke wrote:
> > > On Fri, 2007-08-31 at 12:49 -0700, Remco Treffkorn wrote:
> > > > On Friday 31 August 2007, Joe Marcus Clarke wrote:
> > > > > I dug into the FreeBSD kernel some more, and found that if signal
> > > > > handlers are registered, the tsleep() function will know which
> > > > > signals are allowed to interrupt the ioctl syscall, thus causing it
> > > > > to return EINTR.  Based on this, I put together this patch which
> > > > > fixes the termination problem.  It may not be the ideal place for
> > > > > the signal handler registration, but it does the job.
> > > > >
> > > > > I can send a formal git patch once people have a chance to comment.
> > > > >
> > > > > Joe
> > > >
> > > > So, the VT_WAITACTIVE ioctl returns EINTR when SIGTERM is sent to the
> > > > process? The signal handler should now have been called already.
> > >
> > > It does now.  Before a signal handler is registered, there are no
> > > signals in the sigintr set that can interrupt a syscall.
> > >
> > > > For me that sounds like fixing a symptom, since we really don't
> > > > understand what the problem is.
> > >
> > > I know what the problem is now.  When VT_WAITACTIVE is called in
> > > FreeBSD, the kernel puts the thread to sleep using the tsleep()
> > > function.  This function will only return if the condition is met, or
> > > it is interrupted.  If it is interrupted, but the signal is not in the
> > > sigintr set, tsleep() will return ERESTART, and the ioctl will continue
> > > to call tsleep() (it won't return to the caller since the caller didn't
> > > indicate it wanted the syscall to be interrupted).
> > >
> > > Once a signal handler is registered for a signal, the sigintr set
> > > becomes populated.  Now, tsleep() will check if the signal received is
> > > in the set.  If it is, it returns EINTR, and the ioctl returns EINTR to
> > > its caller (i.e. CK).  The result is the waiting thread continues.
> > >
> > > > Also, returning with EINTR only means the process received a signal.
> > > > Does not have to be SIGTERM.
> > >
> > > Correct.  However, since we had to explicitly register handlers for
> > > those signals we wanted to cause aborts, we can safely assume that if
> > > ioctl returns EINTR in this case (at least on FreeBSD) our process has
> > > received one of SIGTERM, SIGQUIT, SIGHUP, or SIGINT, and we should die.
> > >
> > > Joe
> >
> > I had some time to think about it, and it still disturbs me.
>
> I have been working with the kernel guys on this, and the underlying
> kernel loop will be fixed.  However, it will take time to propagate to
> all versions of FreeBSD.

As always :-)

> > The diff only had the BSD conditional in it. Where is the signal handler
> > for SIGTERM, SIGQUIT, SIGHUP, and SIGINT? Why not just exit from there?
>
> In the meantime, simply registering SIG_DFL for SIGTERM, SIGQUIT,
> SIGHUP, and SIGINT will work to terminate the process in the normal
> cases.

This is really sick! Since SIG_DFL is... ahemm... the default? I think that's 
why they call it a bug.

> > You will then never even get to the goto.
>
> I have a new patch that simply removes the #ifdef around that goto.
> It's not needed.

That's what I thought.

> > How is SIGKILL handled? You indicated BDS had a bug. Are you still saying
> > that?
>
> SIGKILL is not handled because of the loop in the kernel.  Yes it is a
> bug, and it will be fixed, but CK will still need a BSD workaround in
> the meantime.

Thanks. Now it makes sense to me. That is a nasty bug to have, and I am glad 
you found it.

It would be nice, if you could track that, and remove the workaround when the 
kernel is fixed.

Cheers,
Remco

-- 
Remco Treffkorn (RT445)
HAM DC2XT
remco at rvt.com   (831) 685-1201



More information about the hal mailing list