diff options
author | Kurt Miller <kurt@cvs.openbsd.org> | 2007-11-26 19:26:47 +0000 |
---|---|---|
committer | Kurt Miller <kurt@cvs.openbsd.org> | 2007-11-26 19:26:47 +0000 |
commit | 198a0f1343042ea457954a653c6a1b3afdfe48ad (patch) | |
tree | 7946a1d010c51162868b8b6c748866e9cbc8e106 /lib/libc/gen | |
parent | 8374d0a911cddc92acb7b053e07587a174e802e5 (diff) |
make popen/pclose thread safe. closes library/5634. from and okay andreas@
Diffstat (limited to 'lib/libc/gen')
-rw-r--r-- | lib/libc/gen/popen.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c index 5f796e5cee5..d7c6c61731f 100644 --- a/lib/libc/gen/popen.c +++ b/lib/libc/gen/popen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: popen.c,v 1.17 2005/08/08 08:05:34 espie Exp $ */ +/* $OpenBSD: popen.c,v 1.18 2007/11/26 19:26:46 kurt Exp $ */ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. @@ -41,13 +41,16 @@ #include <stdlib.h> #include <string.h> #include <paths.h> +#include "thread_private.h" static struct pid { struct pid *next; FILE *fp; pid_t pid; -} *pidlist; - +} *pidlist; + +static void *pidlist_lock = NULL; + FILE * popen(const char *program, const char *type) { @@ -69,8 +72,10 @@ popen(const char *program, const char *type) return (NULL); } + _MUTEX_LOCK(&pidlist_lock); switch (pid = vfork()) { case -1: /* Error. */ + _MUTEX_UNLOCK(&pidlist_lock); (void)close(pdes[0]); (void)close(pdes[1]); free(cur); @@ -111,6 +116,7 @@ popen(const char *program, const char *type) /* NOTREACHED */ } } + _MUTEX_UNLOCK(&pidlist_lock); /* Parent; assume fdopen can't fail. */ if (*type == 'r') { @@ -124,8 +130,10 @@ popen(const char *program, const char *type) /* Link into list of file descriptors. */ cur->fp = iop; cur->pid = pid; + _MUTEX_LOCK(&pidlist_lock); cur->next = pidlist; pidlist = cur; + _MUTEX_UNLOCK(&pidlist_lock); return (iop); } @@ -143,12 +151,22 @@ pclose(FILE *iop) pid_t pid; /* Find the appropriate file pointer. */ + _MUTEX_LOCK(&pidlist_lock); for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) if (cur->fp == iop) break; - if (cur == NULL) + if (cur == NULL) { + _MUTEX_UNLOCK(&pidlist_lock); return (-1); + } + + /* Remove the entry from the linked list. */ + if (last == NULL) + pidlist = cur->next; + else + last->next = cur->next; + _MUTEX_UNLOCK(&pidlist_lock); (void)fclose(iop); @@ -156,12 +174,7 @@ pclose(FILE *iop) pid = waitpid(cur->pid, &pstat, 0); } while (pid == -1 && errno == EINTR); - /* Remove the entry from the linked list. */ - if (last == NULL) - pidlist = cur->next; - else - last->next = cur->next; free(cur); - + return (pid == -1 ? -1 : pstat); } |