1

アプリケーションを定義しました

{application, ps_barcode,
 [{description, "barcode image generator based on ps-barcode"},
  {vsn, "1.0"},
  {modules, [ps_barcode_app, ps_barcode_supervisor, barcode_data, wand, ps_bc]},
  {registered, [ps_bc, wand, ps_barcode_supervisor]},
  {applications, [kernel, stdlib]},
  {mod, {ps_barcode_app, []}},
  {start_phases, []}]}.

スーパーバイザーは次のようにinit見えます

init([]) ->
    {ok, {{one_for_one, 3, 10},
      [{tag1, 
        {wand, start, []},
        permanent,
        brutal_kill,
        worker,
        [wand]},
       {tag2,
        {ps_bc, start, []},
        permanent,
        10000,
        worker,
        [ps_bc]}]}}.

これは、C コンポーネントを使用して画像処理の一部を行うバーコード ジェネレーターです。存在しないファイルを処理するように求められた場合、または不十分な権限で処理を行うように求められた場合、システムはエラーを起こし、正しく再起動しますが、wandモジュールからのタイムアウトを引き起こす特定のエラーが 1 つあります。

GPL Ghostscript 9.04: Unrecoverable error, exit code 1
GPL Ghostscript 9.04: Unrecoverable error, exit code 1
wand.c barcode_to_png 65 Postscript delegate failed `/tmp/tmp.1337.95765.926102': No such file or directory @ error/ps.c/ReadPSImage/827

** exception exit: {timeout,{gen_server,call,
                    [wand,{process_barcode,"/tmp/tmp.1337.95765.926102"}]}}
     in function  gen_server:call/2 (gen_server.erl, line 180)
     in call from ps_bc:generate/3 (ps_bc.erl, line 19)

(Imagemagick エラーは不正確です。ファイルは存在しますが、エラーのある Postscript ファイルであるため、通常とは解釈できません。それが原因で Ghostscript エラーが発生し、プログラムがハングする原因になっていると思いますが、よくわかりません。なぜまったく返されないのですか)。

私が抱えている問題は、このタイムアウトがエラーを返しても、プロセスがバックグラウンドでハングしているように見えることです (何らかの理由で別のタイムアウトエラーが返さwandれるため、これを結論付けています)。投稿するコードの量がわからないので、モジュール自体に最小限に留めています。他の作品を投稿する必要がある場合はお知らせください。wandwand:stopwand

-module(wand).

-behaviour(gen_server).

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

-export([process/1]).

process(Filename) -> gen_server:call(?MODULE, {process_barcode, Filename}).

handle_call({process_barcode, Filename}, _From, State) ->
    State ! {self(), {command, Filename}},
    receive
      {State, {data, Data}} ->
        {reply, decode(Data), State}
    end;
handle_call({'EXIT', _Port, Reason}, _From, _State) ->
    exit({port_terminated, Reason}).

decode([0]) -> {ok, 0};
decode([1]) -> {error, could_not_read};
decode([2]) -> {error, could_not_write}.

%%%%%%%%%%%%%%%%%%%% generic actions
start() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
stop() -> gen_server:call(?MODULE, stop).

%%%%%%%%%%%%%%%%%%%% gen_server handlers
init([]) -> {ok, open_port({spawn, filename:absname("wand")}, [{packet, 2}])}.
handle_cast(_Msg, State) -> {noreply, State}.
handle_info(_Info, State) -> {noreply, State}.
terminate(_Reason, Port) -> Port ! {self(), close}, ok.
code_change(_OldVsn, State, _Extra) -> {ok, State}.

編集:言及するのを忘れており、関連している可能性があります。application:load/を介してアプリケーションを実行した場合にのみ、ハングが発生するようですapplication:start。このコンポーネントを単独でテストする場合

c(wand).
wand:start().
wand:process("/tmp/tmp.malformed-file.ps").

それでもエラーになりますが、プロセスは実際に停止します。つまり、私はできる

wand:start().
wand:process("/tmp/tmp.existing-well-formed-file.ps").

期待される応答を取得します。スーパーバイザーを介して起動すると、代わりにハングし、前述の動作を示します。

4

2 に答える 2

1

答えではありませんが、そのような場合はどうしますか。私は gen_server:cast を使用し、gen_server でタイムアウトを処理します。すべての作業が完了したら、リクエスタに結果とともに応答を送信します。したがって、この変更はリクエスタ側にも影響します。

しかし、私はあらゆる点で間違っているかもしれません。

于 2012-05-16T02:57:57.020 に答える
0

外部の C プログラムを扱うときにreceive..afterプレーンの代わりに使用すると強制終了されるようです。receive他の対策がうまくいかない理由はわかりませんが...

...
receive
  {State, {data, Data}} ->
    {reply, decode(Data), State}
after 3000 ->
  exit(wand_timeout)
end;
...

また、この時点で、正当な操作に3000. この特定のケースでは問題ではありませんが、C プログラムにさらに出力を追加すると問題になる可能性があります。

于 2012-05-26T02:37:45.537 に答える