Fixed child process signal behaviours. (#128)

* Restored signal handlers upon fork().
* Improved error handling of hpfs process kill scenario.
* Set pgid for forked processes for graceful sending of SIGINT.
This commit is contained in:
Ravin Perera
2020-09-26 21:39:26 +05:30
committed by GitHub
parent 05f356f6e0
commit 4d920a9219
9 changed files with 36 additions and 23 deletions

View File

@@ -62,7 +62,7 @@ namespace comm
else if (pid == 0)
{
// Websocat process.
util::unmask_signal();
util::fork_detach();
close(write_pipe[1]); //parent write
close(read_pipe[0]); //parent read

View File

@@ -295,7 +295,7 @@ namespace comm
else if (pid == 0)
{
// Websocketd process.
util::unmask_signal();
util::fork_detach();
// We are using websocketd forked repo: https://github.com/codetsunami/websocketd

View File

@@ -519,7 +519,7 @@ namespace cons
if (pid == 0)
{
// appbill process.
util::unmask_signal();
util::fork_detach();
// before execution chdir into a valid the latest state data directory that contains an appbill.table
chdir(conf::ctx.state_rw_dir.c_str());

View File

@@ -56,7 +56,7 @@ namespace hpfs
else if (pid == 0)
{
// hpfs process.
util::unmask_signal();
util::fork_detach();
// Fill process args.
char *execv_args[] = {
@@ -145,7 +145,7 @@ namespace hpfs
else if (pid == 0)
{
// hpfs process.
util::unmask_signal();
util::fork_detach();
// If the mount dir is not specified, assign a mount dir based on hpfs process id.
const pid_t self_pid = getpid();

View File

@@ -67,12 +67,12 @@ int parse_cmd(int argc, char **argv)
*/
void deinit()
{
usr::deinit();
p2p::deinit();
cons::deinit();
state_sync::deinit();
state_serve::deinit();
read_req::deinit();
usr::deinit();
p2p::deinit();
hpfs::deinit();
}
@@ -190,8 +190,9 @@ int main(int argc, char **argv)
<< (conf::cfg.startup_mode == conf::OPERATING_MODE::OBSERVER ? "Observer" : "Proposer");
LOG_INFO << "Public key: " << conf::cfg.pubkeyhex.substr(2); // Public key without 'ed' prefix.
if (hpfs::init() != 0 || p2p::init() != 0 || usr::init() != 0 || read_req::init() != 0 ||
state_serve::init() != 0 || state_sync::init() != 0 || cons::init() != 0)
if (hpfs::init() != 0 || read_req::init() != 0 ||
state_serve::init() != 0 || state_sync::init() != 0 || cons::init() != 0 ||
p2p::init() != 0 || usr::init() != 0)
{
deinit();
return -1;
@@ -203,7 +204,7 @@ int main(int argc, char **argv)
// Wait until consensus thread finishes.
cons::wait();
// deinit() here only gets called when there is an error in consensus.
// deinit() here only gets called when there is an error in consensus.
// If not deinit in the sigint handler is called when a SIGINT is received.
deinit();
}

View File

@@ -67,7 +67,7 @@ namespace sc
else if (pid == 0)
{
// Contract process.
util::unmask_signal();
util::fork_detach();
// Set up the process environment and overlay the contract binary program with execv().
@@ -112,7 +112,9 @@ namespace sc
ret = -1;
success:
stop_hpfs_rw_session(ctx);
if (stop_hpfs_rw_session(ctx) == -1)
ret = -1;
cleanup_fdmap(ctx.userfds);
if (!ctx.args.readonly)
{
@@ -131,7 +133,7 @@ namespace sc
{
if (pid > 0)
{
int scstatus;
int scstatus = 0;
waitpid(pid, &scstatus, 0);
if (!WIFEXITED(scstatus))
return WEXITSTATUS(scstatus);
@@ -156,17 +158,18 @@ namespace sc
*/
int stop_hpfs_rw_session(execution_context &ctx)
{
int result = 0;
// Read the root hash if not in readonly mode.
if (!ctx.args.readonly && hpfs::get_hash(ctx.args.post_execution_state_hash, ctx.args.state_dir, "/") < 1)
return -1;
result = -1;
LOG_DEBUG << "Stopping hpfs session... pid:" << ctx.hpfs_pid << (ctx.args.readonly ? " (rdonly)" : "");
if (util::kill_process(ctx.hpfs_pid, true) == -1)
return -1;
result = -1;
ctx.hpfs_pid = 0;
return 0;
return result;
}
/**
@@ -711,9 +714,6 @@ namespace sc
if (ctx.contract_pid > 0)
util::kill_process(ctx.contract_pid, true);
if (ctx.hpfs_pid > 0)
util::kill_process(ctx.hpfs_pid, true);
if (ctx.output_fetcher_thread.joinable())
ctx.output_fetcher_thread.join();
}

View File

@@ -206,13 +206,25 @@ namespace util
pthread_sigmask(SIG_BLOCK, &mask, NULL);
}
// Clears signal mask from the calling thread.
// Used for other processes forked from hpcore threads.
void unmask_signal()
/**
* Clears signal mask and signal handlers from the caller.
* Called by other processes forked from hpcore threads so they get detatched from
* the hpcore signal setup.
*/
void fork_detach()
{
// Restore signal handlers to defaults.
signal(SIGINT, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
signal(SIGABRT, SIG_DFL);
// Remove any signal masks applied by hpcore.
sigset_t mask;
sigemptyset(&mask);
pthread_sigmask(SIG_SETMASK, &mask, NULL);
// Set process group id (so the terminal doesn't send kill signals to forked children).
setpgrp();
}
// Kill a process with a signal and if specified, wait until it stops running.

View File

@@ -90,7 +90,7 @@ namespace util
void mask_signal();
void unmask_signal();
void fork_detach();
int kill_process(const pid_t pid, const bool wait, const int signal = SIGINT);

Binary file not shown.