Выявляем ошибки загрузки своих дополнений для NodeJS
kayo — Чт, 20/09/2012 - 12:28
Статья рассказывает о том, как очень просто выявить ошибку загрузки дополнения (то есть собираемого C++ модуля) для NodeJS, ровно как и в иных приложениях, где подобная ситуация имеет место быть.
Обычно мне не свойственно писать короткие статьи, но тут такое дело, что просто не мог не написать.
Проблема
Случилось тут однажды разрабатывать одно дополнение (то есть собираемый C++ модуль) для NodeJS. На тему в общем-то не мало всего написано, а что не написано, легко постигается на практике. Лишь одна вещь может поставить в некоторого рода тупик неискущенного разработчика, а именно, NodeJS не даёт никакой информации о проблемах загрузки модуля в случае их наличия, он просто сообщает что-то вроде следующего:
$ node test/simple.js module.js:477 process.dlopen(filename, module.exports); ^ Error: Unable to load shared library <…>/build/Release/mgc.node at Object..node (module.js:477:11) at Module.load (module.js:353:32) at Function._load (module.js:311:12) at Module.require (module.js:359:17) at require (module.js:375:17) at Object.<anonymous> (<…>/mgc.js:1:73) at Module._compile (module.js:446:26) at Object..js (module.js:464:10) at Module.load (module.js:353:32) at Function._load (module.js:311:12)
В моём случае вызовом dlopen ноде не удалось загрузить собранный мною модуль с именем «build/Release/mgc.node». Следовало бы ожидать что-то вроде: «не найдена функция инициализации» типа mgc_module, или «найдены неразрешимые символы» такие-то, однако, этого нет, мол, думайте сами, чего у вас там не так.
Решение
Всё было бы весьма печально, если бы не замечательный вызов dlerror и замечательный отладчик GDB. Программа действий следующая:
- В среде отладчика запускаем любой NodeJS модуль, подключающий дополнение (пусть это будет тест)
- Перед стартом процесса устанавливаем точку останова на функцию dlopen
- Стартуем процесс пока не произошел останов
- Переходим к возврату из функции dlopen
- Вызываем dlerror средствами отладчика
- Просматриваем строку ошибки по возвращённой ссылке
В общем-то это и всё, ничего сложного, осталось показать конкретный пример:
$ gdb --args nodejs test/simple.js # стартуем сессию отладки GNU gdb (GDB) 7.0.1-debian Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /usr/bin/nodejs...(no debugging symbols found)...done. (gdb) break dlopen # устанавливаем точку останова Breakpoint 1 at 0x41bf20 (gdb) run # запускаем процесс Starting program: /usr/bin/nodejs test/simple.js [Thread debugging using libthread_db enabled] [New Thread 0x7ffff7ff8700 (LWP 9909)] Breakpoint 1, __dlopen (file=0x777c80 "<…>/build/Release/mgc.node", mode=1) at dlopen.c:76 76 dlopen.c: Нет такого файла или каталога. in dlopen.c (gdb) fin # переходим к моменту возврата из функции Run till exit from #0 __dlopen (file=0x777c80 "<…>/build/Release/mgc.node", mode=1) at dlopen.c:76 0x000000000046346a in uv_dlopen () Value returned is $1 = (void *) 0x0 (gdb) print dlerror() # выполняем вызов dlerror $2 = 7746288 # получили адрес в переменную $2 (gdb) x/s $2 # исследуем содержимое строки по нему 0x7632f0: "<…>/build/Release/mgc.node: undefined symbol: _ZN4node5Magic3tplE" (gdb) quit # теперь всё ясно, завершаем сессию отладки
Столь нехитрый способ оказался весьма полезным, но будем надеяться, что в ветке NodeJS 0.8.x наконец-то внедрят более внятный вывод информации об ошибке с использованием вызова dlerror.

Отправить комментарий