views:

123

answers:

2

I've seen a few implementations of popen()/pclose(). They all used a static list of pids, and no locking:

static int *pids;
static int fds;

if (!pids) {
     if ((fds = getdtablesize()) <= 0)
      return (NULL);
     if ((pids = malloc(fds * sizeof(int))) == NULL)
      return (NULL);
     memset(pids, 0, fds * sizeof(int));
    }

Or this, supposedly NetBSD:

static struct pid {
    struct pid *next;
    FILE *fp;
    pid_t pid;
} *pidlist; 

    /* Link into list of file descriptors. */
    cur->fp = iop;
    cur->pid =  pid;
    cur->next = pidlist;
    pidlist = cur;

Is it what it looks like - a not thread safe implementation? Or am I missing something obvious?

+1  A: 

I don't think you're missing something obvious. I don't see any reference to thread-safety with popen() either requiring it to be thread-safe or not. As a result you should probably treat it as non-thread-safe.

Aaron
I remember when threads were getting supported, man pages used to tell you explicitly if a function was safe or unsafe. Now I expect a function to be safe it not told otherwise..
n-alexander
That would be nice. However - I would reverse your expectation -- functions are generally unsafe unless the author actually thought about the thread issues. And if it's not mentioned in the man page then they probably didn't think about it.
Aaron
At least on Linux, the manpages aren't necessarily written by the glibc folks who write the implementations.
bdonlan
+1  A: 

The GNU libc implementation is threadsafe if libc is configured to be reentrant (which it is likely to be). However, this may not be the case for other implementations of libc.

bdonlan
yes, I see it locks the list of children. This is much better. Thanks for the link.I'd rather popen returned a pid and I passed that to pclose, though, but that's not an option for libc in this case
n-alexander