This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/23398] New: Deadlock in forked child calling system()


https://sourceware.org/bugzilla/show_bug.cgi?id=23398

            Bug ID: 23398
           Summary: Deadlock in forked child calling system()
           Product: glibc
           Version: 2.20
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: libc
          Assignee: unassigned at sourceware dot org
          Reporter: stevecobb47 at yahoo dot com
                CC: drepper.fsp at gmail dot com
  Target Milestone: ---

Hi Folks,

Test case is below. We are seeing a deadlock in system() when a child is 
forked from a multi-threaded process.

The basic scenario is this: let us say we have some number of threads, any of
which may call system(). We have some additional threads, which may call
fork(),
and those forked children may themselves call system().

Referring to sysdeps/posix/system.c:
If a forked child is unlucky, it will inherit the DO_LOCK() lock in a held
state.
So when that forked child calls system, it hangs in the DO_LOCK() code.

#0  __lll_lock_wait_private () at
../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95
#1  0x00007f15281b3574 in do_system (line=0x7ffd2f52cf30 "mkdir -p
/install/tmp/partprep")
    at ../sysdeps/posix/system.c:68

(gdb) frame 1
(gdb) p lock
$8 = 2
(gdb) p sa_refcntr
$9 = 1

The value of sa_refcntr supports this - we have not yet incremented the value,
yet
it is 1. Since this is the forked child, there is only this single thread.

Here is a test case:

#include <assert.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

#define NUM_SYSTEM_THREADS 30
#define NUM_FORKS          100

int stop = 0;

void *run_system(void *arg)
{
  while (!stop) {
    system("true");
  }
  return NULL;
}

int main()
{
  pthread_t pid[NUM_SYSTEM_THREADS];
  int count = 0;
  int i;

  for (i=0; i<NUM_SYSTEM_THREADS; i++) {
    pthread_create(&pid[i], NULL, run_system, NULL);
  }

  while (count++ < NUM_FORKS) {
    int pp[2];
    pipe(pp);
    pid_t p = fork();
    if (p == 0) {
      close(pp[0]);
      system("true");
      exit(0);
    } else if (p > 0) {
      close(pp[1]);
      fd_set readfds;
      FD_ZERO(&readfds);
      FD_SET(pp[0], &readfds);
      select(pp[0]+1, &readfds, NULL, NULL, &(struct timeval){1, 0});
      waitpid(p, NULL, WNOHANG);
      if (kill(p, 0) == 0) {
        printf("Process %d still alive (Try %d)\n", (int)p, count);
        stop = 1;
        for (i=0; i<NUM_SYSTEM_THREADS; i++) {
          pthread_join(pid[i], NULL);
        }
        char cmd[256];
        snprintf(cmd, sizeof(cmd), "pstack %d", (int)p);
        system(cmd);
        kill(p, SIGABRT);
        exit(1);
      }
      close(pp[0]);
    } else {
      perror("fork");
      exit(1);
    }
  }
  printf("Success %d tries\n", count);
  return 0;
}
////////////////////////////////
Process 14252 still alive (Try 1)
#0  0x00007ff541bd9eec in __lll_lock_wait_private () from /lib64/libc.so.6
#1  0x00007ff541b16091 in _L_lock_31 () from /lib64/libc.so.6
#2  0x00007ff541b15bb9 in do_system () from /lib64/libc.so.6
#3  0x00007ff541b16071 in system () from /lib64/libc.so.6
#4  0x0000000000400910 in main ()

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]