Как использовать GDB, чтобы получить трассировку ruby из другого потока
У меня есть программа ruby, которая порождает два потока. Редко кажется, что он висит в главном потоке, и я пытаюсь использовать GDB, чтобы выяснить, почему.
Используя сообщение в блоге, я использовал gdb для подключения к процессу и вызова rb_backtrace()
чтобы получить след.
Проблема в том, что обратная трассировка всегда происходит из одного из порожденных рабочих потоков, а не из основного потока, где я испытываю зависание.
Есть ли способ получить обратную трассировку от определенного потока?
Я попытался с помощью команд GDB info threads
а также thread 2
изменить активный поток, но это не имеет никакого эффекта. Я также пытался использовать ruby_eval
определение в GDB, как описано здесь, но каждый раз, когда я пытаюсь оценить строку кода ruby, я получаю ошибку No symbol table is loaded. Use the "file" command.
Поскольку я работаю над встроенной системой, я не могу скомпилировать ruby с символами GDB.
1 ответ
rb_backtrace()
относится к глобальной переменной, которую вы можете переопределить:
# Make a note of the old thread pointer so you can put it back.
(gdb) p ruby_current_thread
$1 = (rb_thread_t *) 0x5619dfe485e0
(gdb) set ruby_current_thread = 0x5619efb7d3a0
(gdb) p ruby_current_thread
$2 = (rb_thread_t *) 0x5619efb7d3a0
# Write the backtrace to stderr
(gdb) call (void) rb_backtrace()
Указатель рубиновой нити (
0x5619efb7d3a0
выше) можно найти в трассировке GDB интересующего вас нативного потока, например.
#7 0x00005619de86cf96 in vm_exec (th=th@entry=0x5619efb7d3a0) at vm.c:1693
Установить
ruby_current_thread
вернуться к исходному значению перед возобновлением процесса. Проверено на Ruby 2.3.8.