Commit b0a7454f authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Close a couple of races.

parent eb34cf52
...@@ -62,8 +62,9 @@ struct process { ...@@ -62,8 +62,9 @@ struct process {
int fd_from; int fd_from;
pid_t pid; pid_t pid;
pthread_mutex_t mtx;
pthread_t tp; pthread_t tp;
unsigned running; unsigned hasthread;
int status; int status;
}; };
...@@ -95,6 +96,7 @@ process_new(const char *name) ...@@ -95,6 +96,7 @@ process_new(const char *name)
ALLOC_OBJ(p, PROCESS_MAGIC); ALLOC_OBJ(p, PROCESS_MAGIC);
AN(p); AN(p);
REPLACE(p->name, name); REPLACE(p->name, name);
AZ(pthread_mutex_init(&p->mtx, NULL));
p->vl = vtc_logopen(name); p->vl = vtc_logopen(name);
AN(p->vl); AN(p->vl);
...@@ -129,6 +131,7 @@ process_delete(struct process *p) ...@@ -129,6 +131,7 @@ process_delete(struct process *p)
{ {
CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC); CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
AZ(pthread_mutex_destroy(&p->mtx));
vtc_logclose(p->vl); vtc_logclose(p->vl);
free(p->name); free(p->name);
free(p->workdir); free(p->workdir);
...@@ -174,14 +177,22 @@ process_thread(void *priv) ...@@ -174,14 +177,22 @@ process_thread(void *priv)
continue; continue;
} }
r = wait4(p->pid, &p->status, 0, &ru); r = wait4(p->pid, &p->status, 0, &ru);
closefd(&p->fd_to);
AZ(pthread_mutex_lock(&p->mtx));
macro_undef(p->vl, p->name, "pid"); macro_undef(p->vl, p->name, "pid");
p->pid = -1; p->pid = -1;
p->running = 0;
vtc_log(p->vl, 2, "R %d Status: %04x (u %.6f s %.6f)", r, p->status, vtc_log(p->vl, 2, "R 0x%04x Status: %04x (u %.6f s %.6f)",
r, p->status,
ru.ru_utime.tv_sec + 1e-6 * ru.ru_utime.tv_usec, ru.ru_utime.tv_sec + 1e-6 * ru.ru_utime.tv_usec,
ru.ru_stime.tv_sec + 1e-6 * ru.ru_stime.tv_usec ru.ru_stime.tv_sec + 1e-6 * ru.ru_stime.tv_usec
); );
AZ(pthread_mutex_unlock(&p->mtx));
if (WIFEXITED(p->status) && WEXITSTATUS(p->status) == 0) if (WIFEXITED(p->status) && WEXITSTATUS(p->status) == 0)
return (NULL); return (NULL);
#ifdef WCOREDUMP #ifdef WCOREDUMP
...@@ -193,8 +204,6 @@ process_thread(void *priv) ...@@ -193,8 +204,6 @@ process_thread(void *priv)
p->status, WTERMSIG(p->status), WEXITSTATUS(p->status)); p->status, WTERMSIG(p->status), WEXITSTATUS(p->status));
#endif #endif
closefd(&p->fd_to);
return (NULL); return (NULL);
} }
...@@ -207,6 +216,8 @@ process_start(struct process *p) ...@@ -207,6 +216,8 @@ process_start(struct process *p)
int fdt[2]; int fdt[2];
CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC); CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
if (p->hasthread)
vtc_log(p->vl, 0, "Already running, (-wait first)");
vtc_log(p->vl, 4, "CMD: %s", p->spec); vtc_log(p->vl, 4, "CMD: %s", p->spec);
...@@ -227,7 +238,6 @@ process_start(struct process *p) ...@@ -227,7 +238,6 @@ process_start(struct process *p)
} }
p->pid = fork(); p->pid = fork();
assert(p->pid >= 0); assert(p->pid >= 0);
p->running = 1;
if (p->pid == 0) { if (p->pid == 0) {
assert(dup2(fds[0], 0) == 0); assert(dup2(fds[0], 0) == 0);
assert(dup2(out_fd, 1) == 1); assert(dup2(out_fd, 1) == 1);
...@@ -249,6 +259,7 @@ process_start(struct process *p) ...@@ -249,6 +259,7 @@ process_start(struct process *p)
closefd(&err_fd); closefd(&err_fd);
} }
VSB_destroy(&cl); VSB_destroy(&cl);
p->hasthread = 1;
AZ(pthread_create(&p->tp, NULL, process_thread, p)); AZ(pthread_create(&p->tp, NULL, process_thread, p));
} }
...@@ -257,12 +268,14 @@ process_start(struct process *p) ...@@ -257,12 +268,14 @@ process_start(struct process *p)
*/ */
static void static void
process_wait(const struct process *p) process_wait(struct process *p)
{ {
void *v; void *v;
if (p->running && p->pid > 0) if (p->hasthread) {
AZ(pthread_join(p->tp, &v)); AZ(pthread_join(p->tp, &v));
p->hasthread = 0;
}
} }
static void static void
...@@ -278,14 +291,19 @@ process_run(struct process *p) ...@@ -278,14 +291,19 @@ process_run(struct process *p)
*/ */
static void static void
process_kill(const struct process *p, const char *sig) process_kill(struct process *p, const char *sig)
{ {
int j = 0; int j = 0;
pid_t pid;
CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC); CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
AN(sig); AN(sig);
AZ(pthread_mutex_lock(&p->mtx));
pid = p->pid;
AZ(pthread_mutex_unlock(&p->mtx));
if (!p->running || p->pid <= 0) if (pid <= 0)
vtc_log(p->vl, 0, "Cannot signal a non-running process"); vtc_log(p->vl, 0, "Cannot signal a non-running process");
if (!strcmp(sig, "TERM")) if (!strcmp(sig, "TERM"))
...@@ -299,19 +317,20 @@ process_kill(const struct process *p, const char *sig) ...@@ -299,19 +317,20 @@ process_kill(const struct process *p, const char *sig)
else else
vtc_log(p->vl, 0, "Could not grok signal (%s)", sig); vtc_log(p->vl, 0, "Could not grok signal (%s)", sig);
if (kill(-p->pid, j) < 0) if (kill(-pid, j) < 0)
vtc_log(p->vl, 0, "Failed to send signal %d (%s)", j, strerror(errno)); vtc_log(p->vl, 0, "Failed to send signal %d (%s)",
j, strerror(errno));
else else
vtc_log(p->vl, 4, "Sent signal %d", j); vtc_log(p->vl, 4, "Sent signal %d", j);
} }
static inline void static inline void
process_terminate(const struct process *p) process_terminate(struct process *p)
{ {
process_kill(p, "TERM"); process_kill(p, "TERM");
sleep(1); sleep(1);
if (p->running && p->pid > 0) if (p->pid > 0)
process_kill(p, "KILL"); process_kill(p, "KILL");
} }
...@@ -324,7 +343,7 @@ process_write(const struct process *p, const char *text) ...@@ -324,7 +343,7 @@ process_write(const struct process *p, const char *text)
{ {
int r, len; int r, len;
if (!p->running || p->pid <= 0) if (!p->hasthread)
vtc_log(p->vl, 0, "Cannot write to a non-running process"); vtc_log(p->vl, 0, "Cannot write to a non-running process");
len = strlen(text); len = strlen(text);
...@@ -339,7 +358,7 @@ static void ...@@ -339,7 +358,7 @@ static void
process_close(struct process *p) process_close(struct process *p)
{ {
if (!p->running || p->pid <= 0) if (!p->hasthread)
vtc_log(p->vl, 0, "Cannot close on a non-running process"); vtc_log(p->vl, 0, "Cannot close on a non-running process");
closefd(&p->fd_to); closefd(&p->fd_to);
...@@ -403,8 +422,10 @@ cmd_process(CMD_ARGS) ...@@ -403,8 +422,10 @@ cmd_process(CMD_ARGS)
if (av == NULL) { if (av == NULL) {
/* Reset and free */ /* Reset and free */
VTAILQ_FOREACH_SAFE(p, &processes, list, p2) { VTAILQ_FOREACH_SAFE(p, &processes, list, p2) {
if (p->running && p->pid > 0) if (p->pid > 0)
process_terminate(p); process_terminate(p);
if (p->hasthread)
process_wait(p);
VTAILQ_REMOVE(&processes, p, list); VTAILQ_REMOVE(&processes, p, list);
process_delete(p); process_delete(p);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment