LINUX.ORG.RU

Можно ли определить, в каком потоке произошло segfault?


0

3

Пытаюсь найти ошибку в программе. Программулина использует libdbus, соответственно имеется цикл обработки событий и отдельный поток для gui. Кошмар заключается в том, что имеется плавающая ошибка. Возникает она видимо при определенном стечении интервалов времени между отдельными событиями и последовательности событий. Пробовал программулину на 3-х разных машинках - работает. На 4-ой иногда крэшится. Более того, при детальном выводе отладочной инфы получить это фатальное стечение обстоятельств не удается. Но таки один раз зацепил эту ошибку в gdb. Он указал, в процессе выполнения какой библиотечной функции произошло segfault. И вот тут то у меня возник, может быть и глупый, вопрос. А отслеживается ли gdb, в каком именно потоке произошел крэш, если вдруг на многоядерной системе в этот момент времени выполнялись одновременно оба потока?

В QtCreator отслеживается, а поскольку он выступает лишь интерфейсом к gdb — то да, gdb отслеживает поток.

quiet_readonly ★★★★
()

Более того, при детальном выводе отладочной инфы получить это фатальное стечение обстоятельств не удается.

$ ulimit -c unlimited
$./yourprogram
Oh wai... (core dumped)
$gdb --core=./core.#### ./yourprogram
gdb> bt

где-то тут с высокой вероятностью будут КРОВЬ КИШКИфатальная последовательность вызовов, где упала yourmompyourprogram в «виновном» потоке. Как удастся уронить в корку - сможешь этой примерно последовательностью действий сколько угодно раз воспроизвести с одной и той же коры.

slackwarrior ★★★★★
()
Последнее исправление: slackwarrior (всего исправлений: 3)

Может у тебя где проезд по памяти? Попробуй валгринд, если повезет, то он тебя точнее в место бага приведет

AF ★★★
()
Ответ на: комментарий от vertexua

Жужжит она сволочь под valgrind-ом и падать не хочет. Ну находит он мемори лик. Но я и так знаю, что они у меня пока что есть.

zloy_starper ★★★
() автор топика
Ответ на: комментарий от zloy_starper

Доведи параметры работы приложения до критических, 100500 потоков и т.д. Корректная программа должна работать хоть как-то, плохая - взбесится

vertexua ★★★★★
()
Ответ на: комментарий от zloy_starper

За это спасибо, но надо еще ядру сказать, что дампы делало. Впрочем, это я уже нашел, как сделать.

Ещё учти, что на всяких федорах/редхатах в /proc/sys/kernel/core_pattern может быть прописан пайп в abrt (редхатовская приблуда для автоматической генерации багрепортов) и тогда корку ты не получишь.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от vertexua

Это бессмысленно, так как логика программы подразумевает только два потока. В основном потоке крутится GUI. Во втором потоке цикл обработки сообщений от/в dbus. Потоки связаны исключительно двумя очередями сообщений - каждая из них является входящей, или исходящей для одного из потоков. Больше между ними нет пересечений. С конкурентным доступом к очередям падение не может быть связано, т.к.: 1. Все это хозяйство падает, когда очереди пусты. 2. Более того, в GUI еще даже не стартовал цикл обработки событий.

Судя по тому, что выдает отладка, падает эта хрень: 1. Когда dbus поток выполняет первый poll для дескриптора (из poll уже не выходит). 2. Когда GUI поток создает очередной виджет.

Все облазил. Чую, что где-то затаилась совсем глупая очепятка, которую я в упор не вижу.

Вообще, если сделать небольшой таймаут перед стартом второго потока, то падений не наблюдается. Но это меня бесит! Почему на ровном месте такие грабли!!!

zloy_starper ★★★
() автор топика
Ответ на: комментарий от zloy_starper

Вообще, если сделать небольшой таймаут перед стартом второго потока, то падений не наблюдается.

Как будто в обоих потоках используется доступ к общему ресурсу, но при этом только в первом потоке имеется соотв. init/new/... Вот и выходит, что когда первый поток успел произвести инициализацию, всё работает, а когда второй оказался раньше - облом.

gag ★★★★★
()
Ответ на: комментарий от mv

Ну вот приплыли. В момент крэша основной поток вошел в библиотечную функцию XtWidgetToApplicationContext, а второй поток тоже в библиотечную функцию poll.

Thread 2 (Thread 0x7f600fcd4700 (LWP 7501)):
#0  0x00007f6013214703 in poll () from /lib64/libc.so.6
No symbol table info available.
#1  0x0000000000402e05 in IO_Wait (LData=0x665bb0) at xmsvm.c:314
        status = <value optimized out>
        i = <value optimized out>
        new_nhandler = <value optimized out>
        flags = <value optimized out>
        p = <value optimized out>
        base_p = <value optimized out>
        hand_p = 0x0
        tmp_p = <value optimized out>
        spect = {tv_sec = 1369239712, tv_nsec = 924789}
#2  0x0000000000403d68 in MainLoopStart (LData=0x665bb0) at xmsvm.c:1059
No locals.
#3  0x0000000000405b01 in DBusMain () at xmsvm.c:2970
        conn = 0x662a10
        err = {name = 0x0, message = 0x0, dummy1 = 1, dummy2 = 0, dummy3 = 0, dummy4 = 1, dummy5 = 1, padding1 = 0x18}
#4  0x0000000000405b39 in DBusThread (unused=<value optimized out>) at xmsvm.c:2977
No locals.
#5  0x00007f601398b9aa in start_thread () from /lib64/libpthread.so.0
No symbol table info available.
#6  0x00007f601321d14d in clone () from /lib64/libc.so.6
No symbol table info available.
#7  0x0000000000000000 in ?? ()
No symbol table info available.

Thread 1 (Thread 0x7f6013fce740 (LWP 7500)):
#0  0x00007f6012f05961 in XtWidgetToApplicationContext () from /usr/lib64/libXt.so.6
No symbol table info available.
#1  0x00007f60135acffe in XmCreateRadioBox () from /usr/lib64/libXm.so.4
No symbol table info available.
#2  0x00007f60135c4584 in XmCreateSimpleCheckBox () from /usr/lib64/libXm.so.4
No symbol table info available.
#3  0x000000000040680b in main (argc=1, argv=<value optimized out>) at xmsvm.c:3563
---Type <return> to continue, or q <return> to quit---
        thread_id = 140050558699264
        form = 0x6602c0
        child = 0x661b30
        scrolled_win = 0x80018f0
        args = {{name = 0x60ba97 «topAttachment», value = 3}, {name = 0x60bb23 «topWidget», value = 6691632}, {name = 0x60b045 «leftAttachment», value = 1}, {
            name = 0x60b657 «rightAttachment», value = 1}, {name = 0x60a67b «bottomAttachment», value = 1}, {name = 0x60b7a7 «scrollingPolicy», value = 0}, {
            name = 0x7fff52b23b08 «\374G\262R\377\177», value = 140050617251656}, {name = 0x8000 <Address 0x8000 out of bounds>, value = 4221056}, {name = 0x0, value = 4201947}, {
            name = 0x0, value = 4221125}}
        n = 6

zloy_starper ★★★
() автор топика
Ответ на: комментарий от mv

Я ему дамп скормил (если я правильно понял вопрос). Поймать segfault непосредственно под gdb мне надо еще изловчиться.


(gdb) disas
Dump of assembler code for function XtWidgetToApplicationContext:
   0x00007f6012f05960 <+0>:     push   %rbx
=> 0x00007f6012f05961 <+1>:     mov    0x8(%rdi),%rax
   0x00007f6012f05965 <+5>:     mov    %rdi,%rbx
   0x00007f6012f05968 <+8>:     testb  $0x4,0x28(%rax)
   0x00007f6012f0596c <+12>:    je     0x7f6012f05988 <XtWidgetToApplicationContext+40>
   0x00007f6012f0596e <+14>:    mov    0x98(%rdi),%rax
   0x00007f6012f05975 <+21>:    mov    0x8(%rax),%rdi
   0x00007f6012f05979 <+25>:    callq  0x7f6012ef8ea8 <_XtGetPerDisplay@plt>
   0x00007f6012f0597e <+30>:    pop    %rbx
   0x00007f6012f0597f <+31>:    mov    0x20(%rax),%rax
   0x00007f6012f05983 <+35>:    retq   
   0x00007f6012f05984 <+36>:    nopl   0x0(%rax)
   0x00007f6012f05988 <+40>:    callq  0x7f6012ef83a8 <_XtIsHookObject@plt>
   0x00007f6012f0598d <+45>:    test   %al,%al
   0x00007f6012f0598f <+47>:    je     0x7f6012f059a8 <XtWidgetToApplicationContext+72>
   0x00007f6012f05991 <+49>:    mov    0x68(%rbx),%rax
   0x00007f6012f05995 <+53>:    mov    0x8(%rax),%rdi
   0x00007f6012f05999 <+57>:    callq  0x7f6012ef8ea8 <_XtGetPerDisplay@plt>
   0x00007f6012f0599e <+62>:    pop    %rbx
   0x00007f6012f0599f <+63>:    mov    0x20(%rax),%rax
   0x00007f6012f059a3 <+67>:    retq   
   0x00007f6012f059a4 <+68>:    nopl   0x0(%rax)
   0x00007f6012f059a8 <+72>:    mov    %rbx,%rdi
   0x00007f6012f059ab <+75>:    callq  0x7f6012ef8b08 <_XtWindowedAncestor@plt>
   0x00007f6012f059b0 <+80>:    mov    0x98(%rax),%rax
   0x00007f6012f059b7 <+87>:    mov    0x8(%rax),%rdi
   0x00007f6012f059bb <+91>:    callq  0x7f6012ef8ea8 <_XtGetPerDisplay@plt>
   0x00007f6012f059c0 <+96>:    pop    %rbx
   0x00007f6012f059c1 <+97>:    mov    0x20(%rax),%rax
   0x00007f6012f059c5 <+101>:   retq   
End of assembler dump.
(gdb) info reg
rax            0x0      0
rbx            0x80018f0        134224112
rcx            0x0      0
rdx            0x7fff52b23940   140734580799808
rsi            0x407146 4223302
rdi            0x80018f0        134224112
rbp            0x0      0x0
rsp            0x7fff52b237a0   0x7fff52b237a0
r8             0x7f6013ff2003   140050629074947
r9             0x7f6013fce740   140050628929344
r10            0x7fff52b23590   140734580798864
r11            0x7f60135acfd0   140050618306512
r12            0x407146 4223302
r13            0x7fff52b23940   140734580799808
r14            0x0      0
r15            0x80018f0        134224112
rip            0x7f6012f05961   0x7f6012f05961 <XtWidgetToApplicationContext+1>
eflags         0x10202  [ IF RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb)
zloy_starper ★★★
() автор топика
Ответ на: комментарий от mv

Хм ... Даже и не знаю, что тут сказать. Первый аргумент это виджет. До CheckBox-а создаются виджеты: Form Label ScrolledWindow

В первоначальном варианте кода второй поток стартовал до создания всех этих виджетов. И крэш происходил в ScrolledWindow. Потом старт второго потока я передвинул после Form. Для этого варианта я и запостил вывод gdb. Получается, что когда второй поток входит в poll, а в этот момент первый поток входит в библиотечную функцию создания виджета (неважно какого), то портится переменная виджета.

Но это же просто фантастика!! Никто не в курсе может у poll есть какая-нибудь специфика в многопоточном режиме?

zloy_starper ★★★
() автор топика
Ответ на: комментарий от mv
Dump of assembler code for function poll:
   0x00007f60132146b0 <+0>:     sub    $0x28,%rsp
   0x00007f60132146b4 <+4>:     mov    0x2a056e(%rip),%eax        # 0x7f60134b4c28
   0x00007f60132146ba <+10>:    test   %eax,%eax
   0x00007f60132146bc <+12>:    jne    0x7f60132146d5 <poll+37>
   0x00007f60132146be <+14>:    movslq %edx,%rdx
   0x00007f60132146c1 <+17>:    mov    $0x7,%eax
   0x00007f60132146c6 <+22>:    syscall 
   0x00007f60132146c8 <+24>:    cmp    $0xfffffffffffff000,%rax
   0x00007f60132146ce <+30>:    ja     0x7f601321471d <poll+109>
   0x00007f60132146d0 <+32>:    add    $0x28,%rsp
   0x00007f60132146d4 <+36>:    retq   
   0x00007f60132146d5 <+37>:    mov    %edx,0x8(%rsp)
   0x00007f60132146d9 <+41>:    mov    %rsi,0x10(%rsp)
   0x00007f60132146de <+46>:    mov    %rdi,0x18(%rsp)
   0x00007f60132146e3 <+51>:    callq  0x7f6013229f70
   0x00007f60132146e8 <+56>:    mov    0x8(%rsp),%edx
   0x00007f60132146ec <+60>:    mov    %eax,%r8d
   0x00007f60132146ef <+63>:    mov    0x10(%rsp),%rsi
   0x00007f60132146f4 <+68>:    mov    0x18(%rsp),%rdi
   0x00007f60132146f9 <+73>:    mov    $0x7,%eax
   0x00007f60132146fe <+78>:    movslq %edx,%rdx
   0x00007f6013214701 <+81>:    syscall 
=> 0x00007f6013214703 <+83>:    cmp    $0xfffffffffffff000,%rax
   0x00007f6013214709 <+89>:    ja     0x7f601321472f <poll+127>
   0x00007f601321470b <+91>:    mov    %r8d,%edi
   0x00007f601321470e <+94>:    mov    %eax,0x18(%rsp)
   0x00007f6013214712 <+98>:    callq  0x7f6013229fd0
   0x00007f6013214717 <+103>:   mov    0x18(%rsp),%eax
   0x00007f601321471b <+107>:   jmp    0x7f60132146d0 <poll+32>
   0x00007f601321471d <+109>:   mov    0x29a87c(%rip),%rdx        # 0x7f60134aefa0
   0x00007f6013214724 <+116>:   neg    %eax
zloy_starper ★★★
() автор топика
Ответ на: комментарий от zloy_starper

Это без оптимизации.

#0  0x00007fda91cb1961 in XtWidgetToApplicationContext () from /usr/lib64/libXt.so.6
(gdb) thread 2
[Switching to thread 2 (Thread 0x7fda8ea80700 (LWP 8440))]#0  0x00007fda91fc0703 in poll () from /lib64/libc.so.6
(gdb) disas
Dump of assembler code for function poll:
   0x00007fda91fc06b0 <+0>:     sub    $0x28,%rsp
   0x00007fda91fc06b4 <+4>:     mov    0x2a056e(%rip),%eax        # 0x7fda92260c28
   0x00007fda91fc06ba <+10>:    test   %eax,%eax
   0x00007fda91fc06bc <+12>:    jne    0x7fda91fc06d5 <poll+37>
   0x00007fda91fc06be <+14>:    movslq %edx,%rdx
   0x00007fda91fc06c1 <+17>:    mov    $0x7,%eax
   0x00007fda91fc06c6 <+22>:    syscall 
   0x00007fda91fc06c8 <+24>:    cmp    $0xfffffffffffff000,%rax
   0x00007fda91fc06ce <+30>:    ja     0x7fda91fc071d <poll+109>
   0x00007fda91fc06d0 <+32>:    add    $0x28,%rsp
   0x00007fda91fc06d4 <+36>:    retq   
   0x00007fda91fc06d5 <+37>:    mov    %edx,0x8(%rsp)
   0x00007fda91fc06d9 <+41>:    mov    %rsi,0x10(%rsp)
   0x00007fda91fc06de <+46>:    mov    %rdi,0x18(%rsp)
   0x00007fda91fc06e3 <+51>:    callq  0x7fda91fd5f70
   0x00007fda91fc06e8 <+56>:    mov    0x8(%rsp),%edx
   0x00007fda91fc06ec <+60>:    mov    %eax,%r8d
   0x00007fda91fc06ef <+63>:    mov    0x10(%rsp),%rsi
   0x00007fda91fc06f4 <+68>:    mov    0x18(%rsp),%rdi
   0x00007fda91fc06f9 <+73>:    mov    $0x7,%eax
   0x00007fda91fc06fe <+78>:    movslq %edx,%rdx
   0x00007fda91fc0701 <+81>:    syscall 
=> 0x00007fda91fc0703 <+83>:    cmp    $0xfffffffffffff000,%rax
   0x00007fda91fc0709 <+89>:    ja     0x7fda91fc072f <poll+127>
   0x00007fda91fc070b <+91>:    mov    %r8d,%edi
   0x00007fda91fc070e <+94>:    mov    %eax,0x18(%rsp)
   0x00007fda91fc0712 <+98>:    callq  0x7fda91fd5fd0
   0x00007fda91fc0717 <+103>:   mov    0x18(%rsp),%eax
   0x00007fda91fc071b <+107>:   jmp    0x7fda91fc06d0 <poll+32>
   0x00007fda91fc071d <+109>:   mov    0x29a87c(%rip),%rdx        # 0x7fda9225afa0
   0x00007fda91fc0724 <+116>:   neg    %eax
   0x00007fda91fc0726 <+118>:   mov    %eax,%fs:(%rdx)
   0x00007fda91fc0729 <+121>:   or     $0xffffffffffffffff,%rax
   0x00007fda91fc072d <+125>:   jmp    0x7fda91fc06d0 <poll+32>
   0x00007fda91fc072f <+127>:   mov    0x29a86a(%rip),%rdx        # 0x7fda9225afa0
   0x00007fda91fc0736 <+134>:   neg    %eax
   0x00007fda91fc0738 <+136>:   mov    %eax,%fs:(%rdx)
   0x00007fda91fc073b <+139>:   or     $0xffffffffffffffff,%rax
   0x00007fda91fc073f <+143>:   jmp    0x7fda91fc070b <poll+91>
End of assembler dump.
(gdb) frame 1
#1  0x000000000040281a in IO_Wait (LData=0x663d90) at xmsvm.c:321
321             status = poll(LData->ufds, LData->nfds, 50);
(gdb) info locals
status = 0
i = 1
new_nhandler = 1
flags = 0
p = 0x519fc7bd
base_p = 0x663c40
hand_p = 0x0
tmp_p = 0x583d4
spect = {tv_sec = 0, tv_nsec = 6700432}
(gdb) p *LData
$1 = {in_idler = 0, in_io = 0, in_timer = 0, nfds = 1, ufds = 0x663d70, fd_handler = 0x663c40, num_handler = 1, data = 0x0, current_fd_handler = 0, idler_cb = 0x0, idler = 0x666980, num_idler = 2, 
  idler_data = 0x0, current_idler = 0, timer = 0x666920, num_timer = 0, current_timer = 0, exit_loop = 0}
(gdb)
zloy_starper ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.