test_terminal: wait on children to avoid zombies
Unfortunately, there is no clean way I see to hook this up from the pty object. We can (and will) have more than one pty object opened at a time, but the semantics of signalfd make it impossible to deliver each SIGCHLD to its rightful owner without complicating things. [ From what I tested: - If you have two signalfd's listening to the same signal, they will be dispatched in some round-robin manner. - Also, if more than one child exits before we read signalfd (possibly beloging to different terminals), they will be compressed to one event. ] We therefore need to do the reaping from a central location, and need to remember to copy this snippet over to main.c in the future. Signed-off-by: Ran Benita <ran234@gmail.com> Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
6ebc7c1892
commit
5cc190d947
@ -36,6 +36,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "eloop.h"
|
||||
#include "input.h"
|
||||
@ -48,6 +49,7 @@ struct app {
|
||||
struct kmscon_eloop *eloop;
|
||||
struct kmscon_signal *sig_term;
|
||||
struct kmscon_signal *sig_int;
|
||||
struct kmscon_signal *sig_chld;
|
||||
struct kmscon_symbol_table *st;
|
||||
struct kmscon_font_factory *ff;
|
||||
struct kmscon_compositor *comp;
|
||||
@ -63,13 +65,61 @@ static void sig_term(struct kmscon_signal *sig, int signum, void *data)
|
||||
terminate = 1;
|
||||
}
|
||||
|
||||
static void sig_chld(struct kmscon_signal *sig, int signum, void *data)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* If multiple children exit at the same time, signalfd would put them
|
||||
* all in one event. So we reap in a loop.
|
||||
*/
|
||||
while (1) {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
if (pid == -1) {
|
||||
if (errno != ECHILD)
|
||||
log_warning("test: cannot wait on child: %m\n");
|
||||
break;
|
||||
} else if (pid == 0) {
|
||||
break;
|
||||
} else if (WIFEXITED(status)) {
|
||||
if (WEXITSTATUS(status) != 0)
|
||||
log_info("test: child %d exited with status "
|
||||
"%d\n", pid, WEXITSTATUS(status));
|
||||
else
|
||||
log_debug("test: child %d exited "
|
||||
"successfully\n", pid);
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
log_debug("test: child %d exited by signal %d\n", pid,
|
||||
WTERMSIG(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void terminal_closed(struct kmscon_terminal *term, void *data)
|
||||
{
|
||||
/*
|
||||
* Alternativly, we could spwan a new login/shell here, like what
|
||||
* happens when the user exits the shell in a linux console.
|
||||
*/
|
||||
terminate = 1;
|
||||
#if 0
|
||||
/*
|
||||
* Alternativly, we could spwan a new login/shell here, like what
|
||||
* happens when the user exits the shell in a linux console:
|
||||
*/
|
||||
|
||||
int ret;
|
||||
struct app *app = data;
|
||||
|
||||
if (!app)
|
||||
goto err_out;
|
||||
|
||||
ret = kmscon_terminal_open(app->term, app->eloop,
|
||||
terminal_closed, app);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
return;
|
||||
|
||||
err_out:
|
||||
#endif
|
||||
terminate = 1;
|
||||
}
|
||||
|
||||
static void read_input(struct kmscon_input *input,
|
||||
@ -140,6 +190,7 @@ static void destroy_app(struct app *app)
|
||||
kmscon_compositor_unref(app->comp);
|
||||
kmscon_font_factory_unref(app->ff);
|
||||
kmscon_symbol_table_unref(app->st);
|
||||
kmscon_eloop_rm_signal(app->sig_chld);
|
||||
kmscon_eloop_rm_signal(app->sig_int);
|
||||
kmscon_eloop_rm_signal(app->sig_term);
|
||||
kmscon_eloop_unref(app->eloop);
|
||||
@ -163,6 +214,11 @@ static int setup_app(struct app *app)
|
||||
if (ret)
|
||||
goto err_loop;
|
||||
|
||||
ret = kmscon_eloop_new_signal(app->eloop, &app->sig_chld, SIGCHLD,
|
||||
sig_chld, NULL);
|
||||
if (ret)
|
||||
goto err_loop;
|
||||
|
||||
ret = kmscon_symbol_table_new(&app->st);
|
||||
if (ret)
|
||||
goto err_loop;
|
||||
@ -196,7 +252,7 @@ static int setup_app(struct app *app)
|
||||
goto err_loop;
|
||||
|
||||
ret = kmscon_terminal_open(app->term, app->eloop,
|
||||
terminal_closed, NULL);
|
||||
terminal_closed, app);
|
||||
if (ret)
|
||||
goto err_loop;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user