base-linux: let core catch SIGCHLD signals

This commit is contained in:
Norman Feske 2013-01-03 13:20:24 +01:00
parent 62e0dd579e
commit 38272b9172
5 changed files with 51 additions and 15 deletions

View File

@ -48,11 +48,6 @@ void Thread_base::_thread_start()
*/
lx_sigaction(LX_SIGUSR1, empty_signal_handler);
/*
* Prevent children from becoming zombies. (SIG_IGN = 1)
*/
lx_sigaction(LX_SIGCHLD, (void (*)(int))1);
Thread_base * const thread = Thread_base::myself();
/* inform core about the new thread and process ID of the new thread */

View File

@ -80,7 +80,12 @@ inline int lx_kill(int pid, int signal)
inline int lx_create_process(int (*entry)(void *), void *stack, void *arg)
{
int flags = CLONE_VFORK | SIGCHLD;
/*
* The low byte of the flags denotes the signal to be sent to the parent
* when the process terminates. We want core to receive SIGCHLD signals on
* this condition.
*/
int const flags = CLONE_VFORK | LX_SIGCHLD;
return lx_clone((int (*)(void *))entry, stack, flags, arg);
}

View File

@ -32,11 +32,20 @@ using namespace Genode;
*/
static char _core_mem[80*1024*1024];
static Lock _wait_for_exit_lock(Lock::LOCKED); /* exit() sync */
static bool _do_exit = false;
static void signal_handler(int signum)
static void sigint_handler(int signum)
{
_wait_for_exit_lock.unlock();
_do_exit = true;
}
static void sigchld_handler(int signnum)
{
_wait_for_exit_lock.unlock();
raw_write_str("sigchld_handler called\n");
}
@ -44,7 +53,10 @@ Platform::Platform()
: _core_mem_alloc(0)
{
/* catch control-c */
lx_sigaction(2, signal_handler);
lx_sigaction(LX_SIGINT, sigint_handler);
/* catch SIGCHLD */
lx_sigaction(LX_SIGCHLD, sigchld_handler);
/* create resource directory under /tmp */
lx_mkdir(resource_path(), S_IRWXU);
@ -64,9 +76,29 @@ Platform::Platform()
void Platform::wait_for_exit()
{
/* block until exit condition is satisfied */
try { _wait_for_exit_lock.lock(); }
catch (Blocking_canceled) { };
for (;;) {
/*
* Block until a signal occurs.
*/
try { _wait_for_exit_lock.lock(); }
catch (Blocking_canceled) { };
/*
* Each time, the '_wait_for_exit_lock' gets unlocked, we could have
* received either a SIGINT or SIGCHLD. If a SIGINT was received, the
* '_exit' condition will be set.
*/
if (_do_exit)
return;
/*
* If we received a SIGCHLD, we go through the list of our children to
* catch any pending terminated children.
*/
PINF("we should check for pending terminated children");
}
}

View File

@ -27,15 +27,18 @@ static void empty_signal_handler(int) { }
void Thread_base::_thread_start()
{
/*
* Set signal handler such that canceled system calls get not
* transparently retried after a signal gets received.
* Set signal handler such that canceled system calls get not transparently
* retried after a signal gets received.
*/
lx_sigaction(LX_SIGUSR1, empty_signal_handler);
/*
* Prevent children from becoming zombies. (SIG_IGN = 1)
* Deliver SIGCHLD signals to no thread other than the main thread. Core's
* main thread will handle the signals while executing the 'wait_for_exit'
* function, which is known to not hold any locks that would interfere with
* the handling of the signal.
*/
lx_sigaction(LX_SIGCHLD, (void (*)(int))1);
lx_sigsetmask(LX_SIGCHLD, false);
Thread_base::myself()->entry();
Thread_base::myself()->_join_lock.unlock();

View File

@ -237,6 +237,7 @@ inline Genode::addr_t lx_vm_reserve(Genode::addr_t base, Genode::size_t size)
***********************************************************************/
enum {
LX_SIGINT = 2, /* used by core to catch Control-C */
LX_SIGUSR1 = 10, /* used for cancel-blocking mechanism */
LX_SIGCHLD = 17, /* child process changed state, i.e., terminated */
LX_SIGCANCEL = 32, /* accoring to glibc, this equals SIGRTMIN,