Подтвердить что ты не робот

Установка точки останова выхода 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()). Это было бы согласуется с тем фактом, что я не смог поймать это с помощью контрольных точек выхода в отладчике.

4b9b3361

Ответ 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.