Fix raw execution input reader's signal blocking.

Signals are generally blocked within threads in Bro so that the main
thread does all signal handling, however, signal masks are inherited
over fork() and exec(), so they should be unblocked before exec() so
that process can respond to signals normally.

This fixes the raw reader from leaving behind processes that didn't
respond to SIGTERM at shutdown because it was blocked before exec().
This commit is contained in:
Jon Siwek 2013-09-04 10:45:29 -05:00
parent db470a637a
commit ca9b9162a7

View file

@ -14,6 +14,10 @@
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
extern "C" {
#include "setsignal.h"
}
using namespace input::reader; using namespace input::reader;
using threading::Value; using threading::Value;
using threading::Field; using threading::Field;
@ -70,14 +74,14 @@ void Raw::DoClose()
if ( execute && childpid > 0 && kill(childpid, 0) == 0 ) if ( execute && childpid > 0 && kill(childpid, 0) == 0 )
{ {
// kill child process // kill child process
kill(childpid, 15); // sigterm kill(childpid, SIGTERM);
if ( forcekill ) if ( forcekill )
{ {
usleep(200); // 200 msecs should be enough for anyone ;) usleep(200); // 200 msecs should be enough for anyone ;)
if ( kill(childpid, 0) == 0 ) // perhaps it is already gone if ( kill(childpid, 0) == 0 ) // perhaps it is already gone
kill(childpid, 9); // TERMINATE kill(childpid, SIGKILL);
} }
} }
} }
@ -160,6 +164,15 @@ bool Raw::Execute()
close(pipes[stderr_out]); close(pipes[stderr_out]);
// Signal mask is inherited over fork-exec, so reset any ignored
// signals to default behavior and unblock any blocked signals.
setsignal(SIGPIPE, SIG_DFL); // May be ignored when debugging scripts.
sigset_t mask;
sigfillset(&mask);
// Assuming the fork-one model of pthreads' fork(), using sigprocmask()
// makes sense over pthread_sigmask() here.
sigprocmask(SIG_UNBLOCK, &mask, 0);
execl("/bin/sh", "sh", "-c", fname.c_str(), (char*) NULL); execl("/bin/sh", "sh", "-c", fname.c_str(), (char*) NULL);
fprintf(stderr, "Exec failed :(......\n"); fprintf(stderr, "Exec failed :(......\n");
_exit(255); _exit(255);