* Daemonize() should re-parent its caller
@ 2002-01-23 15:54 Alan Stern
2002-01-23 19:46 ` Andrew Morton
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Alan Stern @ 2002-01-23 15:54 UTC (permalink / raw)
To: linux-kernel; +Cc: Alan Cox
Consider the question: what happens when a kernel thread dies? For
the most part this doesn't come up, since most kernel threads stay
alive as long as the system is up. But when a kernel thread dies, the
same thing happens as with any other thread: it becomes a zombie, and
its exit_signal (if any) is posted to its parent.
If the parent is init or another user process, we can reasonably
expect that the zombie will be reaped eventually. But what if the
parent is another kernel thread? This situation arises in the USB
mass-storage device driver, where the device manager and scsi
error-handler threads are spawned (indirectly) by the khubd kernel
thread.
In practice, two problems arise here. First, when the thread is
originally spawned, it typically is not given an exit signal. The
exit_signal value is part of the flags mentioned in the call to
kernel_thread(); the flags argument ought to be something like
CLONE_VM | SIGCHLD. However, people often either don't know to add
the SIGCHLD, or don't consider that the thread might terminate, or are
just lazy, so the SIGCHLD is left out. This can reasonably be
considered an error.
Second, the SIGCHLD is quite likely never to be acted on. Signals
posted to a process get acted on when the flow of control for that
process passes from kernel mode back to user mode. With kernel
threads, this never happens. So even if the parent thread has set its
sigaction for SIGCHLD to be SIG_IGN (so that children are reaped
automatically), the reaping action will not take place.
As a result of these two problems, when such a kernel threads dies, it
hangs around forever as an inaccessible zombie.
The straightforward way for a parent thread to try to solve these
problems is for it to execute
sys_wait4(-1, NULL, WNOHANG | __WALL, NULL);
during its main loop. Even that isn't ideal, because if the child
thread's exit_signal is not set then no signal will be posted, and the
parent won't wake up to execute its main loop. Also, doing this would
mean changing existing drivers, in situations where the original
authors probably never even anticipated that a client routine would
spawn a thread that would need to be reaped. I imagine there aren't
too many places in the kernel where this situation comes up, so this
could be done.
But a more elegant and economical solution is to have the daemonize()
routine automatically re-parent its caller to be a child of init
(assuming the caller's parent isn't init already). At the same time,
the caller's exit_signal should be set to SIGCHLD. This would
definitely solve the problem, and it is unlikely to introduce any
incompatibilities with existing code.
After all, when a user process becomes a daemon, it normally goes
through the whole procedure of forking, letting the parent die, having
the child move to a new session and lose its controlling terminal,
etc. Daemonize() should take care of all this on behalf of its caller
-- that's what it was created for in the first place. Changing
sessions and process groups is already in there; becoming a child of
init should be added.
Here is some example (i.e., untested) code to be added in to
daemonize() to accomplish this:
if (current->c_pptr->pid > 1) {
/* Become a child of init */
write_lock_irq(&tasklist_lock);
if (current->p_ysptr)
current->p_ysptr->p_osptr = current->p_osptr;
else
current->p_pptr->p_cptr = current->p_osptr;
if (current->p_osptr)
current->p_osptr->p_ysptr = current->p_ysptr;
current->p_ysptr = NULL;
current->p_pptr = child_reaper;
current->p_osptr = current->p_pptr->p_cptr;
current->p_pptr->p_cptr = current;
if (current->p_osptr)
current->p_osptr->p_ysptr = current;
write_unlock_irq(&tasklist_lock);
}
current->ptrace = 0;
current->exit_signal = SIGCHLD;
Somebody who understands the details of process management better than
I do might want to make a few adjustments.
Alan Stern
P.S.: I don't subscribe to lkml, so please CC: any replies to me at
<stern@rowland.org>.
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: Daemonize() should re-parent its caller
2002-01-23 15:54 Daemonize() should re-parent its caller Alan Stern
@ 2002-01-23 19:46 ` Andrew Morton
2002-01-23 20:28 ` Alan Stern
2002-01-23 20:58 ` Greg KH
2002-01-27 19:48 ` Alan Cox
2 siblings, 1 reply; 6+ messages in thread
From: Andrew Morton @ 2002-01-23 19:46 UTC (permalink / raw)
To: Alan Stern; +Cc: linux-kernel, Alan Cox
Alan Stern wrote:
>
> Consider the question: what happens when a kernel thread dies? For
> the most part this doesn't come up, since most kernel threads stay
> alive as long as the system is up. But when a kernel thread dies, the
> same thing happens as with any other thread: it becomes a zombie, and
> its exit_signal (if any) is posted to its parent.
>
> ...
>
> But a more elegant and economical solution is to have the daemonize()
> routine automatically re-parent its caller to be a child of init
> (assuming the caller's parent isn't init already). At the same time,
> the caller's exit_signal should be set to SIGCHLD. This would
> definitely solve the problem, and it is unlikely to introduce any
> incompatibilities with existing code.
>
Yes. There's a function in the 2.4 series called reparent_to_init()
whch does this. Typically a kernel thread will call that immediately
after calling daemonize(). It _should_ solve any problem which you're
observing. Could you please test that, and if it fixes the problem
which you're seeing, send a patch to the USB maintainers?
Perhaps we should unconditionally call reparent_to_init() from within
daemonize(). I wimped out on doing that because of the possibility
of strangely breaking something.
Really, an audit of all callers of kernel_thread() is needed, and
most of them should would end up using reparent_to_init(). Difficult
to do in the 2.4 context, so we should only do this when and where
problems are demonstrated.
(But you Cc'ed Alan. Are you using 2.2.x?)
-
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Daemonize() should re-parent its caller
2002-01-23 19:46 ` Andrew Morton
@ 2002-01-23 20:28 ` Alan Stern
0 siblings, 0 replies; 6+ messages in thread
From: Alan Stern @ 2002-01-23 20:28 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, Alan Cox
On Wed, 23 Jan 2002, Andrew Morton wrote:
> Alan Stern wrote:
> >
> > Consider the question: what happens when a kernel thread dies? For
> > the most part this doesn't come up, since most kernel threads stay
> > alive as long as the system is up. But when a kernel thread dies, the
> > same thing happens as with any other thread: it becomes a zombie, and
> > its exit_signal (if any) is posted to its parent.
> >
> > ...
> >
> > But a more elegant and economical solution is to have the daemonize()
> > routine automatically re-parent its caller to be a child of init
> > (assuming the caller's parent isn't init already). At the same time,
> > the caller's exit_signal should be set to SIGCHLD. This would
> > definitely solve the problem, and it is unlikely to introduce any
> > incompatibilities with existing code.
> >
>
> Yes. There's a function in the 2.4 series called reparent_to_init()
> whch does this. Typically a kernel thread will call that immediately
> after calling daemonize(). It _should_ solve any problem which you're
> observing. Could you please test that, and if it fixes the problem
> which you're seeing, send a patch to the USB maintainers?
>
> Perhaps we should unconditionally call reparent_to_init() from within
> daemonize(). I wimped out on doing that because of the possibility
> of strangely breaking something.
>
> Really, an audit of all callers of kernel_thread() is needed, and
> most of them should would end up using reparent_to_init(). Difficult
> to do in the 2.4 context, so we should only do this when and where
> problems are demonstrated.
>
> (But you Cc'ed Alan. Are you using 2.2.x?)
Andrew:
Thanks for your help. I wasn't aware of the existence of
reparent_to_init() -- I wish I knew of some way to find out about all
these little things that get added and changed in various versions of the
kernel. Anyway, I'll check it out, and if it works I'll send a patch to
the USB and the SCSI maintainers.
(In fact, I'm using both 2.2 and 2.4. I Cc'ed Alan Cox because it was
suggested that he would be interested, as the original proposer of
daemonize() -- I don't know if that's true or no. If you're not
interested, Alan, I apologize for bothering you.)
Alan Stern
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Daemonize() should re-parent its caller
2002-01-23 15:54 Daemonize() should re-parent its caller Alan Stern
2002-01-23 19:46 ` Andrew Morton
@ 2002-01-23 20:58 ` Greg KH
2002-01-23 21:18 ` Matthew Dharm
2002-01-27 19:48 ` Alan Cox
2 siblings, 1 reply; 6+ messages in thread
From: Greg KH @ 2002-01-23 20:58 UTC (permalink / raw)
To: Alan Stern; +Cc: linux-kernel
On Wed, Jan 23, 2002 at 10:54:44AM -0500, Alan Stern wrote:
>
> If the parent is init or another user process, we can reasonably
> expect that the zombie will be reaped eventually. But what if the
> parent is another kernel thread? This situation arises in the USB
> mass-storage device driver, where the device manager and scsi
> error-handler threads are spawned (indirectly) by the khubd kernel
> thread.
What problem are you seeing with the khubd and USB mass-storage kernel
threads? There is a patch in the most recent kernel versions that
slightly modifies the usb-storage kernel thread logic, supposedly to fix
a problem that people were having under very long scsi timeouts.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Daemonize() should re-parent its caller
2002-01-23 20:58 ` Greg KH
@ 2002-01-23 21:18 ` Matthew Dharm
0 siblings, 0 replies; 6+ messages in thread
From: Matthew Dharm @ 2002-01-23 21:18 UTC (permalink / raw)
To: Greg KH; +Cc: Alan Stern, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1452 bytes --]
He's looking at the "zombie-thread on unload" problem, which is different
from the "long delay at shutdown" problem.
Matt
On Wed, Jan 23, 2002 at 12:58:04PM -0800, Greg KH wrote:
> On Wed, Jan 23, 2002 at 10:54:44AM -0500, Alan Stern wrote:
> >
> > If the parent is init or another user process, we can reasonably
> > expect that the zombie will be reaped eventually. But what if the
> > parent is another kernel thread? This situation arises in the USB
> > mass-storage device driver, where the device manager and scsi
> > error-handler threads are spawned (indirectly) by the khubd kernel
> > thread.
>
> What problem are you seeing with the khubd and USB mass-storage kernel
> threads? There is a patch in the most recent kernel versions that
> slightly modifies the usb-storage kernel thread logic, supposedly to fix
> a problem that people were having under very long scsi timeouts.
>
> thanks,
>
> greg k-h
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
Matthew Dharm Home: mdharm-usb@one-eyed-alien.net
Maintainer, Linux USB Mass Storage Driver
Pitr! That's brilliant! Funded by Microsoft refunds. What sweet irony!
-- A.J.
User Friendly, 2/15/1999
[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Daemonize() should re-parent its caller
2002-01-23 15:54 Daemonize() should re-parent its caller Alan Stern
2002-01-23 19:46 ` Andrew Morton
2002-01-23 20:58 ` Greg KH
@ 2002-01-27 19:48 ` Alan Cox
2 siblings, 0 replies; 6+ messages in thread
From: Alan Cox @ 2002-01-27 19:48 UTC (permalink / raw)
To: Alan Stern; +Cc: linux-kernel, Alan Cox
> But a more elegant and economical solution is to have the daemonize()
> routine automatically re-parent its caller to be a child of init
> (assuming the caller's parent isn't init already). At the same time,
> the caller's exit_signal should be set to SIGCHLD. This would
> definitely solve the problem, and it is unlikely to introduce any
> incompatibilities with existing code.
We have a seperate reparent_to_init() function in 2.4 to do this. That was
kept seperately mostly to avoid introducing mysterious changes of behaviour
in daemonize() calls during 2.4
For 2.5 I agree, the reparent_to_init belongs in daemonize()
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2002-01-27 19:36 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-01-23 15:54 Daemonize() should re-parent its caller Alan Stern
2002-01-23 19:46 ` Andrew Morton
2002-01-23 20:28 ` Alan Stern
2002-01-23 20:58 ` Greg KH
2002-01-23 21:18 ` Matthew Dharm
2002-01-27 19:48 ` Alan Cox
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox