2012-03-24 2 views
1

трассировки из CoreDump:Процесса Coredumped, но не выглядит как незаконные ссылки в многопоточной программе

#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 

фрагмента коды:

#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 } 

Разборка обижая линии. Я не очень хорошо интерпретации кода сборки, но старался изо всех сил:

 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> 

Распечатка регистров и значений член структуры:

(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}} 

Пожалуйста, дайте мне знать, если моя интерпретация Дис-сборка ОК. И если да, хотелось бы понять, почему gdb не показывает NULL, когда он печатает элементы структуры.

ИЛИ если анализ не идеален, хотелось бы знать фактическую причину coredump. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

  • Благодаря

---- Следующая часть была добавлена ​​позже ----

прокси является многопоточной программы. Выполнение большего количества копаний стало известно, что при возникновении проблемы параллельно выполняются следующие два потока. И когда я избегаю двух функций для параллельной работы, проблема никогда не возникает. Но, дело в том, что я не могу объяснить, как это поведение приводит в исходную проблемную сцену:

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) */ 
    ... 
} 
------------------------------------------------------------ 

В приведенных выше фрагментах, если исполнение осуществляются в порядке, LIne 1, линии 3, линия 2, сцена может произойти. Я ожидаю, что всякий раз, когда встречается незаконная ссылка, он должен немедленно сбрасываться, не пытаясь выполнить LINE 3, что делает его NON NULL. Это определенное поведение, потому что до сих пор у меня есть около 12 выпуклых выпусков одной и той же проблемы, и все они показывают то же самое.

+0

Upvote, потому что я не могу сказать, сколько раз у меня были ошибки ошибок в Googled и не найдено результатов. Это, вероятно, будет очень полезно для кого-то. – CodeMouse92

ответ

1

Это is ясно, что struct_fd->Hdr->info является NULL, поскольку Per Johansson уже ответил.

Однако GDB считает, что это не так. Как это могло быть?

Один из распространенных способов это происходит, когда

  1. изменить расположение struct fdStruct, struct StHdr (или оба), и
  2. вы пренебрегаете, чтобы восстановить все объекты, использующие эти определения

Демонтаж показывает, что offsetof(struct fdStruct, Hdr) == 0x1e8 и offsetof(struct StHdr, info) == 0x158. Посмотрите, что печатает GDB для следующих целей:

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

Я держал пари, что бы напечатать что-то другое, чем 0x1e8 и 0x158.

Если это так, make clean && make может решить проблему.

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 

Это доказывает, что идея GDB о том, как объекты раскладывают в спичках памяти скомпилированный код.

Мы по-прежнему не знаем, соответствует ли идея GDB ценности struct_fd действительной реальностью. Что печатает эти команды?

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

Они должны производить такое же значение (0x18d32760). Предполагая, что это так, единственное другое объяснение, о котором я могу думать, это то, что у вас есть несколько потоков, обращающихся к struct_fd, а другой поток перезаписывает значение, которое раньше было NULL с новым значением.

Я просто заметил ваше обновление на вопрос ;-)

Что я ожидаю, когда нелегальная ссылка встречается она должна сбросить сразу, не пытаясь выполнить ЛИНИЮ 3, что делает его NON NULL.

Ваши ожидания неверно: на любом современном процессоре, у вас есть несколько ядер, а ваши потоки выполняются одновременно . То есть, у вас есть этот код (время идет вниз по оси Y):

char *p; // global 


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

В T1, cpu0 ловушки в ОС, но CPU1 продолжается. В конечном итоге ОС перехватывает аппаратную ловушку и записывает состояние памяти в то время. На CPU1 сотни команд могут выполняться после T1. Часы между CPU0 и CPU1 даже не синхронизированы, они не обязательно проходят блокировку.

Мораль истории: не следует обращаться к глобальным переменным из нескольких потоков без надлежащей блокировки.

+0

Спасибо за ваш ответ, на самом деле попробовал это. (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 Пробовал «сделать чистым» и сделать слишком –

+0

Привет @Employed Russian, добавили дополнительную информацию на вопрос. –

+0

@Saj_Rk И я обновил ответ примерно в то же время. Неясно, прочитали ли вы обновление или нет. –

0

Линия сборки линии C не соответствует той, что находится в исходном коде. Но ясно

struct_fd->Hdr->info 

NULL. gdb не должен иметь проблемы с печатью, но иногда это путает, когда код компилируется с -O2 или выше.

+0

Привет, спасибо, что ответили. Я думаю, что часть, которая не совпала, была именем функции в демонстрационной сборке, это была моя неудачная попытка переименовать функции для простоты ;-). Но, я уверен, что двоичный файл не был выполнен с оптимизацией и -g. Все еще можно путать gdb ?? ....Кстати, хотелось бы понять, почему вопрос был отклонен, так что я могу быть точным в их создании. –