Как отладить приложение erlang, которое не загружается

Если я напишу какой-нибудь код на erlang для построения дерева наблюдения, а затем запущу приложение при загрузке с помощью следующей команды, может быть очень сложно понять, почему оно не работает:

erl -s myapp -pa ebin ... ...

(пример модуля myapp)

-module(myapp).
-export([start/0]).
start() -> application:start(myapp).

Допустим, мое приложение запускает супервизор myapp_sup. myapp_sup в свою очередь запускает несколько супервизоров (скажем, server_sup, database_sup, Another_sup).

Эти супервизоры запустят несколько gen_servers.

В какой-то момент, если в моем коде есть ошибка, я не могу ее найти!

Я написал вызов somemodule:functionthatdoesnexists() в обратном вызове инициализации некоторого gen_server.

Все, что vm говорит, это «завершение инициализации при загрузке», а затем отображение местоположения ошибки несоответствия, точного файла и строки моего верхнего модуля (myapp).

(Плохое соответствие, потому что ok = application:start(...) не будет соответствовать).

Я смотрю в файле erl_crash.dump, и там нет информации об этой неопределенной функции (но я нахожу ее в списке атомов).

Итак, я написал некоторый журнал, чтобы примерно увидеть, где ошибка, но затем мне придется запустить мои gen_servers вручную, чтобы получить правильную информацию об ошибке.

Что я упускаю, как я могу понять это быстрее?

Спасибо


person lud    schedule 24.01.2013    source источник


Ответы (2)


Если ваше приложение вызывает неизвестный модуль, ваш файл erl_crash.dump будет содержать строку, подобную этой:

41DABB8:t4:A8:nonexistent_module,A7:unknown,N,N

где «неизвестно» в строке означает, что модуль nonexistent_module не может быть найден. В таких случаях может помочь поиск в файле erl_crash.dump строки «неизвестно».

Если вы подозреваете, что определенный модуль вызывает несуществующую функцию, вы можете найти ее, используя инструмент внешних ссылок в интерактивной оболочке erl. Убедитесь, что вы скомпилировали модуль с отладочной информацией (обычно через erlc +debug_info), затем:

1> xref:m(my_module).
[{deprecated,[]},
 {undefined,[{{my_module,init,1},{another_module,unknown,0}}]},
 {unused,[]}]

Здесь xref показывает нам, что функция my_module:init/1 вызывает функцию another_module:unknown/0, но функция unknown/0 не определена в another_module.

Вы также можете использовать xref для проверки целых приложений; подробности см. в документации.

person Steve Vinoski    schedule 25.01.2013
comment
Спасибо за ваш ответ. Но у меня не такой результат как у тебя. Ни для несуществующего модуля, ни для несуществующей функции в реальном модуле. Я добавил xref в свой make-файл, это легко с арматурой, спасибо. Но проблема остается, скажем, я неправильно написал порт, который слушает база данных, например... Проблема в том, что вы не знаете, какую ошибку вы ищете большую часть времени. - person lud; 26.01.2013
comment
Результат, показанный выше, был получен с использованием Erlang/OTP R15B03 (erts 5.9.3.1); возможно, ваша версия отличается. - person Steve Vinoski; 26.01.2013
comment
Вам также следует подумать о реализации модульных тестов для ваших модулей, так как они могут довольно хорошо обнаруживать такие проблемы, как неправильно написанные атомы или другие имена. - person Steve Vinoski; 26.01.2013
comment
Та же версия, другая конфигурация, я полагаю. Вы правы, я действительно должен пойти на TDD. Я не привык к этому в Erlang, я попробую. - person lud; 28.01.2013
comment
Я разрабатываю небольшое приложение в эти дни, я начал с eunit. Во время тестов вместо отказов с неясными сообщениями Eunit дает мне точную строку кода, где возникают ошибки. Это действительно мило. так что спасибо еще раз. - person lud; 07.02.2013

Добавьте -init_debug к вашей команде erl :)

person Soup d'Campbells    schedule 25.01.2013
comment
Спасибо, но это не решает проблему: ошибки, исходящие из пользовательского кода, не возникают в последовательности загрузки. Они приходят после. С '-init_debug' больше нет информации о моей функции undef. - person lud; 25.01.2013