2012-03-24 6 views
1

Backtrace des coredump:Prozess Coredumped aber sieht nicht wie illegale Referenz in einem multithreaded Programm

#0 0x0000000000416228 in add_to_epoll (struct_fd=0x18d32760, lno=7901) at lbi.c:7092 
#1 0x0000000000418b54 in connect_fc (struct_fd=0x18d32760, type=2) at lbi.c:7901 
#2 0x0000000000418660 in poll_fc (arg=0x0) at lbi.c:7686 
#3 0x00000030926064a7 in start_thread() from /lib64/libpthread.so.0 
#4 0x0000003091ed3c2d in clone() from /lib64/libc.so.6 

Code Snippet:

#define unExp(x) __builtin_expect((x),0) 
... 
7087 int add_to_epoll(struct fdStruct * struct_fd, int lno) 
7088 { 
7089 struct epoll_event ev; 
7090 ev.events = EPOLLIN | EPOLLET | EPOLLPRI | EPOLLERR ; 
7091 ev.data.fd = fd_st->fd; 
7092 if (unExp(epoll_ctl(struct_fd->Hdr->info->epollfd, EPOLL_CTL_ADD,   struct_fd->fd,&ev) == -1)) 
7093 { 
7094  perror("client FD ADD to epoll error:"); 
7095  return -1; 
7096 } 
7097 else 
7098 { 
      ... 
7109 } 
7110 return 1; 
7111 } 

Zerlegen der Codezeile. Ich bin nicht gut in Assembler-Code zu interpretieren, sondern haben versucht, mein Bestes:

 if (unExp(epoll_ctl(struct_fd->Hdr->info->epollfd, EPOLL_CTL_ADD, stuct_fd->fd,&ev) == -1)) 
    416210:  48 8b 45 d8    mov 0xffffffffffffffd8(%rbp),%rax // Storing struct_fd->fd 
    416214:  8b 10     mov (%rax),%edx     // to EDX 
    416216:  48 8b 45 d8    mov 0xffffffffffffffd8(%rbp),%rax // Storing struct_fd->Hdr->info->epollfd 
    41621a:  48 8b 80 e8 01 00 00 mov 0x1e8(%rax),%rax    // to EDI which failed 
    416221:  48 8b 80 58 01 00 00 mov 0x158(%rax),%rax    // while trying to offset members of the structure 
    416228:  8b 78 5c    mov 0x5c(%rax),%edi    // <--- failed here since Reg AX is 0x0 
    41622b:  48 8d 4d e0    lea 0xffffffffffffffe0(%rbp),%rcx 
    41622f:  be 01 00 00 00   mov $0x1,%esi 
    416234:  e8 b7 e1 fe ff   callq 4043f0 <[email protected]> 
    416239:  83 f8 ff    cmp $0xffffffffffffffff,%eax 
    41623c:  0f 94 c0    sete %al 
    41623f:  0f b6 c0    movzbl %al,%eax 
    416242:  48 85 c0    test %rax,%rax 
    416245:  74 5e     je  4162a5 <add_to_epoll+0xc9> 

Ausdrucken Register und struct Elementwerte:

(gdb) i r $rax 
rax   0x0  0 
(gdb) p struct_fd 
$3 = (struct fdStruct *) 0x18d32760 
(gdb) p struct_fd->Hdr 
$4 = (StHdr *) 0x3b990f30 
(gdb) p struct_fd->Hdr->info 
$5 = (struct Info *) 0x3b95b410 // Strangely, this is NOT NULL. Inconsistent with assembly dump. 
(gdb) p ev 
$6 = {events = 2147483659, data = {ptr = 0x573dc648000003d6, fd = 982, u32 = 982, u64= 6286398667419026390}} 

Bitte lassen Sie mich wissen, ob meine dis-Montage Interpretation OK. Und wenn ja, würde gerne verstehen, warum gdb beim Ausdrucken der Strukturelemente NULL nicht anzeigt.

ODER wenn die Analyse nicht perfekt ist, würde gerne den tatsächlichen Grund von Coredump wissen. Bitte lassen Sie mich wissen, wenn Sie weitere Informationen benötigen.

  • Dank

---- Der folgende Teil Später ---- hinzugefügt wurde

Der Proxy ein multithreaded Programm. Wenn Sie mehr graben, wissen Sie, dass die folgenden zwei Threads parallel ausgeführt werden, wenn das Problem auftritt. Und wenn ich die beiden Funktionen parallel laufe, tritt das Problem nie auf. Aber die Sache kann ich nicht erklären, wie dieses Verhalten führt in die ursprüngliche problematische Szene:

Thread 1: 
------------------------------------------------------------ 
int new_connection() { 
    ... 
    struct_fd->Hdr->info=NULL; /* (line 1) */ 
    ... 
    <some code> 
    ... 
    struct_fd->Hdr->info=Golbal_InFo_Ptr; /* (line 2) */ // This is a malloced memory, once allocated never freed 
    ... 
    ... 
} 
------------------------------------------------------------ 

Thread 2 executing add_to_epoll(): 
------------------------------------------------------------ 
int add_to_epoll(struct fdStruct * struct_fd, int lno) 
{ 
    ... 
    if (unExp(epoll_ctl(struct_fd->Hdr->info->epollfd,...) /* (line 3) */ 
    ... 
} 
------------------------------------------------------------ 

In dem obigen Schnipsel, wenn die Ausführung in der Reihenfolge erfolgt, Linie 1, Linie 3, Linie 2, Die Szene kann auftreten. Was ich erwarte ist, wann immer eine illegale Referenz gefunden wird, sollte sie sofort dumpen, ohne zu versuchen, LINE 3 auszuführen, was sie NON NULL macht. Es ist ein bestimmtes Verhalten, denn bis jetzt habe ich ungefähr 12 Coredumps des gleichen Problems, die alle genau das Gleiche zeigen.

+0

Upvote weil, ich kann nicht sagen, wie oft ich Googled Fehlerausgaben hatte und keine Ergebnisse gefunden. Dies wird wahrscheinlich sehr nützlich für jemanden sein. – CodeMouse92

Antwort

1

Es ist klar, dass struct_fd->Hdr->info ist NULL, wie Per Johansson bereits beantwortet.

Allerdings denkt GDB, dass es nicht ist. Wie kann das sein?

Eine übliche Art und Weise dies geschieht, ist, wenn

  1. Sie das Layout struct fdStruct ändern, struct StHdr (oder beides), und
  2. Sie alle Objekte neu zu erstellen vernachlässigen, dass diese Definitionen verwenden

Die Demontage zeigt, dass offsetof(struct fdStruct, Hdr) == 0x1e8 und offsetof(struct StHdr, info) == 0x158. Sehen Sie, was GDB druckt nach folgenden Kriterien:

(gdb) print/x (char*)&struct_fd->Hdr - (char*)struct_fd 
(gdb) print/x (char*)&struct_fd->Hdr->info - (char*)struct_fd->Hdr 

Ich wette, es ist etwas anderes als 0x1e8 und 0x158 drucken. Wenn das der Fall ist, kann make clean && make das Problem beheben.

Update:

(gdb) print/x (char*)&struct_fd->Hdr - (char*)struct_fd 
$1 = 0x1e8 
(gdb) print/x (char*)&struct_fd->Hdr->info - (char*)struct_fd->Hdr 
$3 = 0x158 

Dies beweist, dass GDB Vorstellung davon, wie Objekte im Speicher Streichhölzer Code kompiliert angelegt.

Wir wissen immer noch nicht, ob GDBs Idee des Wertes von struct_fd der Realität entspricht. Was drucken diese Befehle?

(gdb) print struct_fd 
(gdb) x/gx $rbp-40 

Sie sollten den gleichen Wert erzeugen (0x18d32760). Angenommen, sie tun dies, die einzige andere Erklärung, die ich mir vorstellen kann, ist, dass Sie mehrere Threads haben, die auf struct_fd zugreifen, und der andere Thread überschreibt den Wert, der zuvor NULL war, mit dem neuen Wert.

ich nur bemerkt Ihr Update auf die Frage ;-)

Was ich erwarte, ist, wenn eine illegale Referenz es ohne zu versuchen, LINE 3-Dump sofort angetroffen wird, sollte auszuführen, die es NICHT NULL macht.

Ihre Erwartung ist falsch: auf jedem modernen CPU, Sie mehr Kerne und Threads gleichzeitig ausgeführt werden. Das heißt, Sie haben diesen Code (Zeit geht nach unten entlang der Y-Achse):

char *p; // global 


Time  CPU0     CPU1 
0  p = NULL 
1  if (*p)    p = malloc(1) 
2        *p = 'a'; 
... 

Bei T1 CPU0 Fallen in das Betriebssystem, sondern CPU1 weiter. Schließlich verarbeitet das Betriebssystem den Hardware-Trap und gibt zu diesem Zeitpunkt den Speicherstatus aus. Auf CPU1 können Hunderte von Anweisungen nach T1 ausgeführt worden sein. Die Uhren zwischen CPU0 und CPU1 sind nicht einmal synchronisiert, sie gehen nicht unbedingt in Lock-Step.

Moral der Geschichte: nicht globale Variablen aus mehreren Threads ohne ordnungsgemäße Verriegelung zugreifen.

+0

Vielen Dank für Ihre Antwort, hatte es tatsächlich versucht. (gdb) print/x (char *) & struct_fd-> Hdr - (char *) struct_fd $ 1 = 0x1e8 (gdb) drucken/x (char *) & struct_fd-> Hdr-> info - (char *) struct_fd-> Hdr $ 3 = 0x158 Versucht 'make clean' und mache auch –

+0

Hi @Employed Russian, Habe noch ein paar Infos zur Frage hinzugefügt. –

+0

@Saj_Rk Und ich habe die Antwort ungefähr zur gleichen Zeit aktualisiert. Es ist nicht klar, ob Sie das Update gelesen haben oder nicht. –

0

Der C-Line-Teil der Disassemblierung stimmt nicht mit dem Originalcode überein. Aber klar

struct_fd->Hdr->info 

ist NULL. gdb sollte kein Problem beim Drucken haben, aber es wird manchmal verwirrt, wenn der Code mit -O2 oder höher kompiliert wird.

+0

Hallo Per, Danke für die Antwort. Ich denke, der Teil, der nicht übereinstimmte, war der Name der Funktion in der Dis-Assembly, es war mein fehlgeschlagener Versuch, Funktionen der Einfachheit halber umzubenennen ;-). Aber ich bin mir sicher, dass die Binärdatei keiner Optimierung entspricht und -g eingeschaltet war. Kann GDB noch verwirrt werden ?? ....Übrigens, ich würde gerne verstehen, warum die Frage abgelehnt wurde, damit ich sie präzise gestalten kann. –

Verwandte Themen