Установка точки останова выхода gdb не работает?
Я установил точки останова при выходе и _exit, и моя программа (многопоточное приложение, работающая на linux 2.6.16.46-0.12 sles10), как-то все еще выходит, так что я не могу найти
(gdb) c
...
[New Thread 47513671297344 (LWP 15279)]
[New Thread 47513667103040 (LWP 15280)]
[New Thread 47513662908736 (LWP 15281)]
Program exited with code 0177.
(gdb)
функции выхода находятся в libc, поэтому нет проблем с разделяемой библиотекой отложенной нагрузки. Кто-нибудь знает какой-то другой таинственный триггер для выхода, который нельзя поймать?
РЕДАКТИРОВАТЬ: проблема теперь только академическая. Я попробовал двоичную поисковую отладку, выделив подмножество моих изменений (проблема исчезла). После того, как я применил их снова последовательно, я больше не могу воспроизвести проблему, даже если вещи восстановлены в исходное состояние.
EDIT2: Недавно я нашел одну причину такого рода ошибок, который, возможно, был исходным источником этой проблемы. По историческим причинам наш продукт использует злой флаг компоновщика -Bsymbolic. Среди побочных эффектов этого является то, что когда символ undefined, но вызываемый, компоновщик времени выполнения GLIBC будет бомбить именно таким образом, и вы видите его в отладчике как процесс, выходящий с 0177. Когда компоновщик времени выполнения прерывает этот путь, Я бы предположил, что syscall явно работает _exit (вместо использования библиотеки времени выполнения C() или _exit()). Это было бы согласуется с тем фактом, что я не смог поймать это с помощью контрольных точек выхода в отладчике.
Ответы
Ответ 1
Есть две распространенные причины для точки останова _exit
"пропустить" - либо GDB
не установил точку останова в нужном месте, либо программа выполняет (моральный эквивалент) syscall(SYS_exit, ...)
Что говорят info break
и disassemble _exit
?
Возможно, вы сможете убедить GDB
правильно установить точку останова с помощью break *&_exit
. Альтернативно, GDB-7.0
поддерживает catch syscall
. Что-то вроде этого должно работать (при условии Linux/x86_64
, обратите внимание, что на ix86
числа будут отличаться) независимо от того, как программа выйдет:
(gdb) catch syscall 60
Catchpoint 3 (syscall 'exit' [60])
(gdb) catch syscall 231
Catchpoint 4 (syscall 'exit_group' [231])
(gdb) c
Catchpoint 4 (call to syscall 'exit_group'), 0x00007ffff7912f3d in _exit () from /lib/libc.so.6
Обновление:
Ваш комментарий указывает, что контрольная точка _exit установлена правильно, поэтому, вероятно, ваш процесс просто не выполнит _exit
.
Это оставляет syscall(SYS_exit, ...)
и еще одну возможность (которую я пропустил раньше): все потоки выполняются pthread_exit
. Возможно, вам захочется также установить точку останова на pthread_exit
(и выполнить info thread
каждый раз, когда вы нажмете на нее), последний поток для выполнения pthread_exit
приведет к завершению процесса).
Edit:
Также стоит отметить, что вы можете использовать мнемонические имена, а не номера системных вызовов. Вы также можете одновременно добавить несколько системных вызовов в список catch, например:
(gdb) catch syscall exit exit_group
Catchpoint 2 (syscalls 'exit' [1] 'exit_group' [252])
Ответ 2
Установка контрольной точки на _exit была хорошей идеей.
Вы также можете попытаться установить статическую привязку, чтобы просто удалить стек потенциальных gdb-осложнений из таблицы.
0177 подозрительно похож на статус ожидания wait(2)
возвращает для дочернего остановленного, но gdb печатает статус выхода, что совсем другое, поэтому, вероятно, настоящий аргумент выхода.
Ответ 3
Возможно, у вас есть несколько ленивых ссылок, не разрешенных в какой-либо общей библиотеке, загруженной в процесс. У меня точно такая же ситуация, что "кто-то где-то" вышел из процесса и оказался нерешенной ссылкой.
Проверьте свой процесс с помощью опции "ldd -r".
Похоже на ld.so или что-то вроде ленивого разрешения некоторых символов на единую функцию выхода (которая должна прерывать IMHO).
Моя ситуация:
$ ldd ./program
undefined symbol: XXXX (/usr/lib/libYYY.so)
$./program
program: started!
...
<program is running regardless of undefined references>
Теперь выход появился, когда я вызывал какой-то сценарий, который использовал функцию undefined. Он всегда выходил с exitcode = 127, а gdb - 0177.