This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/23398] New: Deadlock in forked child calling system()
- From: "stevecobb47 at yahoo dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Tue, 10 Jul 2018 17:14:39 +0000
- Subject: [Bug libc/23398] New: Deadlock in forked child calling system()
- Auto-submitted: auto-generated
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.