Как использовать 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.

Другие вопросы по тегам