Page MenuHomeFreeBSD

rtsold: ignore SIGCHLD to reap the casper daemon
AbandonedPublic

Authored by bapt on Wed, Sep 2, 4:09 PM.
Tags
None
Referenced Files
F170664678: D59323.id.diff
Sat, Sep 5, 9:55 PM
F170639748: D59323.id185633.diff
Sat, Sep 5, 6:31 PM
F170639659: D59323.id185633.diff
Sat, Sep 5, 6:31 PM
F170495529: D59323.id185633.diff
Sat, Sep 5, 2:33 AM
F170495087: D59323.diff
Sat, Sep 5, 2:30 AM
Unknown Object (File)
Fri, Sep 4, 10:55 PM
Unknown Object (File)
Fri, Sep 4, 7:34 PM
Unknown Object (File)
Fri, Sep 4, 5:17 PM
Subscribers

Details

Reviewers
markj
kib
Summary

rtsold closes the casper channel after opening its services; the
kernel then kills the casper daemon with SIGKILL when the last
process descriptor is closed. As rtsold never waits for children,
the casper daemon lingers as a zombie for the process lifetime.

Commit bcdb6ba94d08 stopped unconditionally reparenting a pdfork(2)
child to init(8) when its last process descriptor is closed: the
parent is now expected to wait(2) or ignore SIGCHLD.

Ignore SIGCHLD so the kernel reaps exited children automatically.
Scripts are run by the rtsold.script service, so script status
handling is unaffected.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 76406
Build 73289: arc lint + arc unit

Event Timeline

bapt requested review of this revision.Wed, Sep 2, 4:09 PM

I am really not confident about this one, I tried to put all my understanding of the situation in the commit log, so reviewer can see what I understood

This is reproducible with rtsold -a -i with any kernel from after july I have not bissect to confirm 100% it appeared since @kib commit. bug adding this change fixes the issue here I don't see any zombie left.

Are you stating that libcapser does not waitpid() on the resulting pid after pdfork()? If yes, the proper solution is to add PD_NOWAITPID to pdfork() call. This should fix it for all consumers.

Ignore SIGCHLD so the kernel reaps exited children automatically. Scripts are run by the rtsold.script service, so script status handling is unaffected.

Not true: you are ignoring SIGCHLD before creating casper services, so the services will inherit the signal mask, and they will also ignore SIGCHLD.

In D59323#1361227, @kib wrote:

Are you stating that libcapser does not waitpid() on the resulting pid after pdfork()? If yes, the proper solution is to add PD_NOWAITPID to pdfork() call. This should fix it for all consumers.

Yes, but this is a kernel regression no? I hadn't realized that pdfork() children are reaped automatically upon close().

In D59323#1361227, @kib wrote:

Are you stating that libcapser does not waitpid() on the resulting pid after pdfork()? If yes, the proper solution is to add PD_NOWAITPID to pdfork() call. This should fix it for all consumers.

Yes, but this is a kernel regression no? I hadn't realized that pdfork() children are reaped automatically upon close().

This was a deliberate change. As was discussed in the corresponding reviews, the behavior was both inconsistent and useless. Whatever happen first (waitpid()/close()/pdwait()) reaped and steal the exit status from other consumers.

In D59323#1361268, @kib wrote:
In D59323#1361227, @kib wrote:

Are you stating that libcapser does not waitpid() on the resulting pid after pdfork()? If yes, the proper solution is to add PD_NOWAITPID to pdfork() call. This should fix it for all consumers.

Yes, but this is a kernel regression no? I hadn't realized that pdfork() children are reaped automatically upon close().

This was a deliberate change. As was discussed in the corresponding reviews, the behavior was both inconsistent and useless. Whatever happen first (waitpid()/close()/pdwait()) reaped and steal the exit status from other consumers.

Then I agree we should modify libcasper as you said.

In D59323#1361268, @kib wrote:
In D59323#1361227, @kib wrote:

Are you stating that libcapser does not waitpid() on the resulting pid after pdfork()? If yes, the proper solution is to add PD_NOWAITPID to pdfork() call. This should fix it for all consumers.

Yes, but this is a kernel regression no? I hadn't realized that pdfork() children are reaped automatically upon close().

This was a deliberate change. As was discussed in the corresponding reviews, the behavior was both inconsistent and useless. Whatever happen first (waitpid()/close()/pdwait()) reaped and steal the exit status from other consumers.

Then I agree we should modify libcasper as you said.

Thinking a bit more, should we convert PD_NOWAITPID -> PD_WAITPID? i.e., invert the default meaning of the flag, to avoid breaking compatibility.

In D59323#1361268, @kib wrote:
In D59323#1361227, @kib wrote:

Are you stating that libcapser does not waitpid() on the resulting pid after pdfork()? If yes, the proper solution is to add PD_NOWAITPID to pdfork() call. This should fix it for all consumers.

Yes, but this is a kernel regression no? I hadn't realized that pdfork() children are reaped automatically upon close().

This was a deliberate change. As was discussed in the corresponding reviews, the behavior was both inconsistent and useless. Whatever happen first (waitpid()/close()/pdwait()) reaped and steal the exit status from other consumers.

Then I agree we should modify libcasper as you said.

Thinking a bit more, should we convert PD_NOWAITPID -> PD_WAITPID? i.e., invert the default meaning of the flag, to avoid breaking compatibility.

It would still break things. If you remember, there was a code that allowed waitpi() to reap the child, if waitpid() was called before close()/pdwait(). From the motivational part of the commit that enabled that even for cap mode (with some further bugs), it seemed to me that the consumers were gtk-based apps d0675399d09f02d347912e23d004329710338450. So when I considered adding PD_NOWAITPID or PD_WAITPID, I selected to require waitpid(2) by default.

We might add a global knob to make pdfork() behave as if PD_NOWAITPID is specified always. This would be an ideal form of the API anyway.