summaryrefslogtreecommitdiff
path: root/lib/libc/gen
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2007-11-26 19:26:47 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2007-11-26 19:26:47 +0000
commit198a0f1343042ea457954a653c6a1b3afdfe48ad (patch)
tree7946a1d010c51162868b8b6c748866e9cbc8e106 /lib/libc/gen
parent8374d0a911cddc92acb7b053e07587a174e802e5 (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.c33
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);
}