действительно ли popen потокобезопасен? - PullRequest
0 голосов
/ 21 января 2019

В последнее время у меня возникают проблемы с вызовом popen, кажется, что он не безопасен для потоков.

Ниже приведен фрагмент кода из ссылки на исходный код: http://androidxref.com/9.0.0_r3/xref/bionic/libc/upstream-netbsd/lib/libc/gen/popen.c

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

static rwlock_t pidlist_lock = RWLOCK_INITIALIZER;

FILE *
popen(const char *command, const char *type)
{
   struct pid *cur, *old;
   ...
   pipe2(pdes, flags)                 // A
   ...
   (void)rwlock_rdlock(&pidlist_lock);     // C
   ...
   switch (pid = vfork()) {                // C.1
     case 0:             /* Child. */
        ...
        _exit(127);
        /* NOTREACHED */
    }

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

   (void)rwlock_unlock(&pidlist_lock); // F
   ...
}

Наблюдая за приведенным выше кодом, он получил блокировку чтения в C, но внутри области он выполнил некоторые операции записи в E. Так что, возможно, будет несколько потоков чтения, которые записывают в переменную "pidlist" вв то же время.

Кто-нибудь знает, является ли это истинной проблемой или нет?

1 Ответ

0 голосов
/ 21 января 2019

Глядя на код, это не то, как вы его обрисовали.

Вот паста по данной ссылке http://androidxref.com/9.0.0_r3/xref/bionic/libc/upstream-netbsd/lib/libc/gen/popen.c

80FILE *
81popen(const char *command, const char *type)
82{
83  struct pid *cur, *old;
94  if (strchr(xtype, '+')) {
...
100 } else  {
103     if (pipe2(pdes, flags) == -1)
104         return NULL;
105 }
106
...
113
114 (void)rwlock_rdlock(&pidlist_lock);
115 (void)__readlockenv();
116 switch (pid = vfork()) {
117 case -1:            /* Error. */
...
127 case 0:             /* Child. */
...
154     execl(_PATH_BSHELL, "sh", "-c", command, NULL);
155     _exit(127);
156     /* NOTREACHED */
157 }
158 (void)__unlockenv();
159
160 /* Parent; assume fdopen can't fail. */
161 if (*xtype == 'r') {
...
167 } else {
...
173 }
...
179 pidlist = cur;
180 (void)rwlock_unlock(&pidlist_lock);
181
182 return (iop);
183}

Это

do the file stuff (pipe2() or socketpair())
acquire the lock (this will avoid the child doing silly things)
vfork()
on the child, reorganize filedes and execl
on parent do some filedes stuff unlock and return

Я не вижу, в чем проблема.

...