1

私が使用しているこの gen_server があります。

-module(user_info_provider).
-export([start_link/0, stop/0]).
-export([init/1, terminate/2, handle_info/2, handle_call/3, handle_cast/2,
 code_change/3]).
-export([request_user_info/2]).

-behaviour(gen_server).

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

stop() ->
    gen_server:cast(?MODULE, stop).

request_user_info(From,UserId) ->
    gen_server:cast(?MODULE, {request_user_info, From, UserId}).
%% Callback Functions
init(_) ->
    process_flag(trap_exit, true),
    io:format("I am ~w ~n", [self()]),
    {ok, null}.
%% @doc terminate
terminate(Reason, _LoopData) ->
    io:format("Terminating by ~w~n",[Reason]),
    {ok, null}.
handle_cast({request_user_info,From,UserId}, LoopData) ->
    {noreply, LoopData};
handle_cast(stop, LoopData) ->
    {stop, normal, LoopData}.
handle_info(_Info, State) ->
    {ok, State}.
code_change(_OldVsn, State, _Extra) ->
    {ok, State}.
handle_call(_,_From,LoopData) ->
    {ok,ok,LoopData}.

問題は、次に示すように、cli から実行するとerl -pa ebin/ -s user_info_provider start_linkすぐに死ぬように見えますが、コンソールから起動して動作することです。

erl -pa ebin -s user_info_provider start_link
Erlang R14B02 (erts-5.8.3) [source] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]

I am <0.32.0> 
Terminating by normal
Eshell V5.8.3  (abort with ^G)
1> user_info_provider:start_link().
I am <0.35.0> 
{ok,<0.35.0>}

これは、設定しないかprocess_flag(trap_exit, true)、コンソールから直接起動しないと発生しません-s module function
実際の gen_server はもっと複雑で、Makefile 呼び出しからスタンドアロンでテストしているので、そのように起動します。
何か案は?

4

2 に答える 2

5

解決策は、 のみW55tKQbuRu28Q4xvを使用するか使用しないかによって提案されるものです。何が起こるかは次のとおりです。start_linkstart

-sパラメータは によって処理されますinit。大まかに言うと、init はspawn新しいプロセスを作成し、それを使用してすべての-sパラメーターを初期化して実行します。その後、この生成されたプロセスは終了します。

init-process が終了し、exit をトラップするため、プロセスはinit によって生成されたプロセスの pid() である{'EXIT', P, Reason}というメッセージを受け取ります。Pこのメッセージは、プロセスのgen_server一部によって処理されます。通常、このようなメッセージはhandle_info/2コールバックに転送されます (コードの戻り値が間違っているため、noreply にする必要があります)。ただし、この場合は転送されませんその理由は、 aにはそのプロセスgen_serverの概念が含まれているためです。プロセス ディクショナリとによってそこに置かれた値を使用して、どのプロセスがそれを生成したかを記録します。ここで、親から終了メッセージが届いた場合'$ancestors'proc_lib、その後すぐに終了コールバックが呼び出され、プロセスが終了します。このようなメッセージは転送されません。これはあなたが見るものです。

解決策、かなりの解決策は、小さなアプリケーション、つまりスーパーバイザーを作成し、プロセスをそのスーパーバイザーの下に置くことです。次にapplication:start(your_app)、-s から呼び出します。これが機能する理由は、アプリケーション コントローラーが個別に実行されるためです。さらに良い解決策は、アプリケーションを自動的に起動するリリースをビルドすることです。リリースは、アプリケーションとその依存関係が ERTS ランタイムにバンドルされたものです。このようなリリースは完全に単独で動作し、ターゲット ホストにコピーして実行できます。リリースは自己完結型であるため、ターゲット システムに Erlang は必要ありません。

于 2011-10-13T12:00:49.190 に答える
1

スーパーバイザーで最小限のアプリケーションを実行し (rebar はそのようなアプリケーションのスケルトンを生成できます)、-s を使用して cli から実行します。

于 2011-10-12T17:51:38.690 に答える