2017-10-23 5 views
2

Ich laufe in ein ziemlich nerviges Problem: Ich habe ein Programm, das einen Thread am Anfang erstellt, dieser Thread wird andere Sachen während seiner Ausführung starten (fork() unmittelbar gefolgt von execve()). HierDeadlock (fork + malloc) libc (glibc-2.17, glibc-2.23)

ist die bt beiden Fäden an dem Punkt, wo mein Programm erreicht (glaube ich) aus der Sackgasse:

Thread 2 (LWP 8839):

# 0 0x00007ffff6cdf736 in __libc_fork() an .. /sysdeps/nptl/fork.c:125

# 0x00007ffff6c8f8c0 1 in _IO_new_proc_open (fp = fp @ entry = 0x7ffff00031d0, command = Befehl @ entry = 0x7ffff6c26e20 "ps -u Brejon | grep \" cvc \“

# 2 0x00007ffff6c8fbcc in _IO_new_popen (Befehl = 0x7ffff6c26e20 "ps -u user | grep \ "cvc \" | wc -l“, mode = 0x42c7fd "r") bei iopopen.c: 296

# 3-4 ...

# 5 0x00007ffff74d9434 in start_thread (arg = 0x7ffff6c27700) bei pthread_create.c: 333

# 6 0x00007ffff6d0fcfd in clone() bei ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

Thread 1 (LWP 8835):

# 0 __lll_lock_wait_private() bei ../sysdeps/unix/sysv/linux/x86_64/lowlevelock.S:95

# 1 0x00007ffff6ca0ad9 in malloc_atfork (sz = 140737337120848, Anrufer =) bei arena.c: 179

# 2 0x00007ffff6c8d875 in __GI__IO_file_doallocate (fp = 0x17a72230) bei filedoalloc.c: 127

# 3 0x00007ffff6c9a964 in __GI__IO_doallocbuf (fp = fp @ entry = 0x17a72230) bei genops.c: 398

# 4 0x00007ffff6c99de8 in _IO_new_file_overflow (f = 0x17a72230, CH = -1) bei fileops.c: 820

# 5 0x00007ffff6c98f8a in _IO_new_file_xsputn (f = 0x17a72230, Daten = 0x17a16420, n = 682) bei fileps.c: 1331

# 6 0x00007ffff6c6fcb2 in _IO_vfprintf_internal (s = 0x17a72230, format = AP = AP @ entry = 0x7fffffffcf18) bei vfprintf.c: 1632

# 7 0x00007ffff6c76a97 in __fprintf (stream =, format =) bei fprintf. c: 32

# 8-11 ...

# 12 0x000000000042706e in main (argc = 3, argv = 0x7fffffffd698, envp = 0x7fffffffd6b8) bei Netz/ignore/.c: 146

Both bleibt hier für immer mit glibc-2.17 und glibc-2 fest.23

Jede Hilfe ist willkommen: 'D

EDIT:

Hier ist ein minimales Beispiel:

1 #include <stdlib.h> 
    2 #include <pthread.h> 
    3 #include <unistd.h> 
    4 
    5 void * thread_handler(void * args) 
    6 { 
    7   char * argv[] = { "/usr/bin/ls" }; 
    8   char * newargv[] = { "/usr/bin/ls", NULL }; 
    9   char * newenviron[] = { NULL }; 
10   while (1) { 
11     if (vfork() == 0) { 
12       execve(argv[0], newargv, newenviron); 
13     } 
14   } 
15 
16   return 0; 
17 } 
18 
19 int main(void) 
20 { 
21   pthread_t thread; 
22   pthread_create(&thread, NULL, thread_handler, NULL); 
23 
24   int * dummy_alloc; 
25 
26   while (1) { 
27     dummy_alloc = malloc(sizeof(int)); 
28     free(dummy_alloc); 
29   } 
30 
31   return 0; 
32 } 

Umwelt: Benutzer: Deadlock $ cat/etc/redhat-release

Wissenschaftliche Linux-Version 7.3 (Stickstoff)

Benutzer: Deadlock $ ldd --Version

LDD (GNU libc) 2,17

EDIT 2: Die rpm-Paket Version ist: glibc-2.17-196.el7.x86_64

kann ich nicht Holen Sie sich die Zeilennummern mit dem RPM-Paket. Hier ist der BT, der den glibc verwendet, der mit der Distribution gegeben wurde: gelöst mit debuginfo.

(GDB) Gewinde gelten alle bt

Thread 2 (Thread 0x7ffff77fb700 (LWP 59753)):

# 0 vfork() bei ../sysdeps/unix/sysv/linux/x86_64/vfork .S: 44

# 1 0x000000000040074e in thread_handler (args = 0x0) bei deadlock.c: 11

# 2 0x00007ffff7bc6e25 in start_thread (arg = 0x7ffff77fb700) bei pthread_create.c: 308

# 3 0x00007ffff78f434d in clone() bei ../sysdeps/unix/sysv/linux/x86_64/clone.S:113

Thread 1 (Thread 0x7ffff7fba740 (LWP 59746)):

# 0 0x00007ffff7878226 in _int_free (av = 0x7ffff7bb8760, p = 0x602240, have_lock = 0) bei malloc.c: 3927

# 1 0x00000000004007aa in main() bei deadlock.c: 28

+2

Können Sie ein [minimales, vollständiges und überprüfbares Beispiel?] (Https://stackoverflow.com/help/mcve) eingeben – mgarey

+0

Bitte geben Sie den Code ein. –

+0

Hi, Aufruf von Fork in einem Multithread-Programme würde Probleme führen, wenn in Thread aufgerufen kopiert den gesamten Adressraum, aber klont keinen Thread, außer dem Thread, der es aufgerufen hat. Dies würde zu einer dauerhaften Ressourcensperre führen. Dieses Verhalten ist in POSIX definiert. –

Antwort

2

Dies ist ein kunden kompilierten glibc. Es ist möglich, dass bei der Installation etwas schief gelaufen ist. Beachten Sie, dass Red Hat Enterprise Linux 7.4 backports a fix for a deadlock between malloc and fork, und Sie vermissen, weil Sie Ihre eigenen Glibc kompiliert haben. Die fix for the upstream bug ging nur in Upstream-Version 2.24, also, wenn Sie Ihre benutzerdefinierte Build darauf basieren, haben Sie möglicherweise nicht diese Korrektur. (Obwohl die Backtrace für diese eine andere aussehen würde.)

Ich denke, wir haben mindestens eine andere Post-2.17-Libio-Deadlock Bug behoben.

BEARBEITEN Ich habe zu lange mit Gabel-Deadlocks zu tun gehabt. Es gibt mehrere Probleme mit dem Reproduzenten wie gepostet:

  • Es gibt keine waitpid Aufruf für die PID. Als Ergebnis wird die Prozesstabelle schnell mit Zombies gefüllt.
  • Keine Fehlerprüfung für execve.Wenn der Pfadname /usr/bin/ls nicht existiert (z. B. auf einem System, das keine UsrMove durchlaufen hat), wird execve zurückgegeben, und die nächste Iteration der Schleife wird gestartet ein weiterervfork Aufruf.
  • Ich habe beide Probleme behoben (weil das Debuggen, was sich einer Gabelbombe nähert, macht überhaupt keinen Spaß), aber ich kann einen Hang mit glibc-2.17-196.el7.x86_64 nicht reproduzieren.

    +0

    Der Deadlock passiert mit der libc (2.17), die auch mit der Distribution (7.3) angegeben wird, also sollte ich die rückportierte Korrektur darin haben (was keine Lösung für den Fehler ist, den ich habe, wenn das der Fall ist). Ich werde versuchen, eine 2.24. –

    +0

    Bitte schreiben Sie das Backtrace mit den Zeilennummern aus dem Distributionspaket und der genauen Version des RPM-Pakets, damit wir das Backtrace mit dem Quellcode abgleichen können. –

    +0

    Ich habe den ersten Beitrag mit diesen Informationen bearbeitet, konnte aber nicht die Zeilennummern für die libc-Verteilung erhalten. –