[PATCH] tfork
Jeremy Allison
jra at samba.org
Wed Apr 19 20:32:57 UTC 2017
On Tue, Apr 18, 2017 at 09:55:56PM +0200, Ralph Böhme via samba-technical wrote:
> Hi!
>
> Attached is a patchset that adds a signal and waitpid() avoiding fork()
> replacement: tfork().
>
> It was based on an older patchset from metze, called double_fork at that time,
> that I extended to fork three-times in order to return a pollable status fd.
>
> It's intented use is in samba_runcmd_send() where it avoids calling waitpid()
> and dealing with SIGCHLD to get the exit status of the executed command.
>
> With this change it is safe to call samba_runcmd_send() in smbd code as an async
> replacement for smbrun().
>
> I have a usecase here where someone wants to run shell scripts from source3
> code without blocking.
>
> Please review & push if happy.
OK, there's one comment I want to raise and discuss
before pushing. Not sure if it matters, but at least it's
something we need to have considered I think.
Inside this code you use CatchSignal() to set and remove the
signal handler for SIGTERM in the parent.
Inside CatchSignal() we have:
ZERO_STRUCT(act);
act.sa_handler = handler;
#ifdef SA_RESTART
/*
* We *want* SIGALRM to interrupt a system call.
*/
if(signum != SIGALRM)
act.sa_flags = SA_RESTART;
which means that on any signal != SIGALRM we *always* set
the SA_RESTART flag to restart slow system calls.
However, inside lib/tevent/tevent_signal.c we have:
struct sigaction act;
ZERO_STRUCT(act);
act.sa_handler = tevent_common_signal_handler;
act.sa_flags = sa_flags;
....
if (sigaction(signum, &act, sig_state->oldact[signum]) == -1) {
where sa_flags is passed in from the caller of
tevent_add_signal().
All of the callers to tevent_add_signal() I can
find don't use SA_RESTART flags. They all pass
zero in the sa_flags parameter, which means that no slow
system calls will be restarted if the caught signal
is received.
In addition, CatchSignal() only returns the old
act.sa_handler, *not* the content of the old act.sa_flags.
Which means when you call CatchSignal() to temporarily
replace a signal handler added by tevent_add_signal()
and then call CatchSignal() to put it back, you
overwrite any sa_flags that were passed into the
tevent_add_signal() call (not that there are any
right now :-), and will always add in SA_RESTART.
So depending on the order of calling CatchSignal()
or tevent_add_signal() we're going to get different
signal handling behavior (restart or not) on slow
system calls.
This patch doesn't make it any worse though :-).
But long run I think we need to remove all
#ifdef HAVE_SIGACTION tests and just *require*
sigaction for Samba to run.
Then we need to look at fixing CatchSignal()
to take a struct sigaction, and return the existing
struct sigaction instead of void, so it can
be used inside library code to temporarily
replace an existing tevent_add_signal() handler
and correctly replace it.
Eventually we might want to look at removing
the use of CatchSignal() and varients entirely.
Thoughts ?
I'm still reviewing the code, and this discussion
can go on in parallel with pushing this - this
code doesn't make the problem any worse than it
already is :-).
Cheers,
Jeremy.
More information about the samba-technical
mailing list