From dfebfa3c8c985ca7fdcc44026253d61d98089c95 Mon Sep 17 00:00:00 2001 From: Michael Santos Date: Wed, 12 Mar 2014 16:59:21 -0400 Subject: [PATCH] Try not to leak PID slots Set a flag when a child exits, then free the slot when all the fd's associated with the child have been marked as closed. Presumably this should prevent the situation where a signal has occurred but there is pending data on an fd. In this case, the parent would previously discard the data and free the slot immediately. --- c_src/alcove.c | 27 +++++++++++++++++++++------ c_src/alcove.h | 1 + 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/c_src/alcove.c b/c_src/alcove.c index 83ff129..e363727 100644 --- a/c_src/alcove.c +++ b/c_src/alcove.c @@ -53,7 +53,8 @@ static ssize_t alcove_child_stdio(int fdin, pid_t pid, u_int16_t type); static ssize_t alcove_write(u_int16_t, ETERM *); static ssize_t alcove_read(int, void *, ssize_t); -static int zero_pid(alcove_child_t *c, void *arg1, void *arg2); +static int exited_pid(alcove_child_t *c, void *arg1, void *arg2); +static int free_pid(alcove_child_t *c, void *arg1, void *arg2); static int set_pid(alcove_child_t *c, void *arg1, void *arg2); static int write_to_pid(alcove_child_t *c, void *arg1, void *arg2); static int read_from_pid(alcove_child_t *c, void *arg1, void *arg2); @@ -130,13 +131,14 @@ alcove_ctl(alcove_state_t *ap) case 0: break; default: - ap->nchild--; - (void)pid_foreach(ap, pid, NULL, NULL, pid_equal, zero_pid); + (void)pid_foreach(ap, pid, NULL, NULL, pid_equal, exited_pid); } child_exited = 0; } + (void)pid_foreach(ap, 0, ap, NULL, pid_not_equal, free_pid); + FD_ZERO(&rfds); FD_SET(STDIN_FILENO, &rfds); @@ -414,15 +416,28 @@ pid_not_equal(pid_t p1, pid_t p2) } static int -zero_pid(alcove_child_t *c, void *arg1, void *arg2) +exited_pid(alcove_child_t *c, void *arg1, void *arg2) { (void)close(c->fdin); c->fdin = -1; - c->pid = 0; - + c->exited = 1; return 0; } + static int +free_pid(alcove_child_t *c, void *arg1, void *arg2) +{ + alcove_state_t *ap = arg1; + + if (c->exited && c->fdout == -1 && c->fderr == -1) { + c->pid = 0; + c->exited = 0; + ap->nchild--; + } + + return 1; +} + static int set_pid(alcove_child_t *c, void *arg1, void *arg2) { diff --git a/c_src/alcove.h b/c_src/alcove.h index 13ec52b..783edec 100644 --- a/c_src/alcove.h +++ b/c_src/alcove.h @@ -40,6 +40,7 @@ enum { typedef struct { pid_t pid; + int exited; int fdin; int fdout; int fderr;