为什么process_flag陷阱退出不起作用?

时间:2013-06-05 21:50:41

标签: erlang

当我尝试使用“process_flag”来捕获孩子的错误报告时,日志显示trap_exit不起作用。这个问题让我麻烦了20个小时。

以下日志不包含应在此处显示的陷阱日志,如" lager:info("loop_1_0,~p,~p",[From,Reason]); %%<---should show this line."

(emacs@yus-iMac.local)20> 05:18:26.048 [info] test_a_1
05:18:26.249 [info] levi_simulate_init_1,false
05:18:26.250 [error] gen_server pid_simulate_reader_user terminated with reason: no match of right hand value 3 in levi_simulate:handle_call/3 line 471
05:18:26.250 [error] CRASH REPORT Process pid_simulate_reader_user with 0 neighbours exited with reason: no match of right hand value 3 in levi_simulate:handle_call/3 line 471 in gen_server:terminate/6 line 747

==以下是我的示例代码:

1. `levi_simulate_tests.erl` main content

error_test_a()->
    close_server(?PID_SIMULATE_READER_USER),
    timer:sleep(200),
    lager:info("test_a_1"),
    spawn_trap_exit(fun crash_test_a/0),
    pass.

spawn_trap_exit(Fun)->
        _Pid = spawn(fun()->
                             process_flag(trap_exit,true),
                             Fun(),
                             loop(),
                             lager:info("receive_after loop")
                     end).
loop()->
        receive
            {'EXIT',From,Reason}->
                lager:info("loop_1_0,~p,~p",[From,Reason]); %%<---should show this line.
            X ->
                lager:info("loop_2,~p",[X]),
                loop()
        after 3000 ->
                ok
        end.
crash_test_a()->
        close_server(?PID_SIMULATE_READER_USER),
        timer:sleep(200),
       {ok,Pid} = levi_simulate:start_link(false,?PID_SIMULATE_READER_USER,true,[]),
        Id = 1,
        gen_server:call(Pid,{test_only}),
        ok.
 close_server(Server)->    
        try
            Pid = whereis(Server),
            case is_process_alive(Pid) of
                true ->
                   exit(Pid,shut);
                false ->
                    ok
            end
        catch
            _:_->
                ok
        end.

===

2. levi_simulate.erl main content
-module(levi_simulate).
-compile([{parse_transform, lager_transform}]).
-behaviour(gen_server).

start_link(Need_link_ui_pid,Server_name,Connection_condition,
           Tag_id_list) ->
    gen_server:start_link({local,Server_name},?MODULE, 
                          [Need_link_ui_pid,Server_name,
                           Connection_condition,Tag_id_list], []).

init([Need_link_ui_pid,Server_name,Connection_condition,Tag_id_list]) ->
    case Need_link_ui_pid of
        true ->
            true = erlang:link(whereis(?PID_UI));
        false ->
            lager:info("levi_simulate_init_1,false"),
            ok
    end,     
    %% A = 2,
    %% A = 3,
    ok = levi_tag:init(Tag_id_list),
    {ok, #state{connection_condition=Connection_condition,
                pid_symbol = Server_name}}.

handle_call(Request, From, State) ->
    A = 2,
    A = 3,    %% <------ create exit here
    {reply,ok,State}.

1 个答案:

答案 0 :(得分:1)

一个原因可能是当您在handle_call/3中生成错误时,它会导致gen_server:call/2生成异常并导致调用进程崩溃。您将永远不会输入loop/0功能。测试此问题的简便方法是用

替换gen_server调用
catch gen_server:call(Pid,{test_only}),

看看会发生什么。