7

gen_server正常に停止したり、予期せずクラッシュしたりするたびに、状態をクリーンアップする必要がある実行中です。クリーンアップは、基本的にいくつかのファイルを削除することから成ります。

この時点で、gen_serverクラッシュまたは正常に停止すると、 でクリーンアップが行われterminate/2ます。

クラッシュterminate/2した場合に呼び出されない理由はありますか?gen_server

予期せずgen_server終了した場合、クリーンアップを実行するのを待機している他のプロセスを監視する必要がありますか?gen_server

したがって、コードは次のようになります。

terminate(normal, State) ->
    % Invoked when the process stops
    % Clean up the mess
terminate(Error, State) ->
    % Invoked when the process crashes
    % Clean up the mess

編集:公式のメーリングリストで同じことについて話しているこのメールを見つけました:

http://groups.google.com/group/erlang-programming/browse_thread/thread/9a1ba2d974775ce8

Adam が以下で述べているように、exists を にトラップすることを避けたい場合は、gen_server別のアプローチを使用できます。

しかし、exists をトラップするterminate/2と、常に呼び出されるため、クリーンアップを行うのに安全な場所と思われます。さらに、'EXIT'が送信されterminate/2たときに正しく処理しhandle_call/3、ワーカーとスーパーバイザーの間でエラーを正しく伝達する必要があります。

4

2 に答える 2

11

terminate/2は、出口をトラップしなくても内部でクラッシュが発生したときに呼び出されgen_serverます。リンクされている他のプロセスから「EXIT」を受け取った場合は呼び出されません。クリーンアップが必要な場合は、出口をトラップする必要があります(を使用してprocess_flag(trap_exit, true))。

この動作は、プロセスの信頼できるシャットダウン手順を作成するのが困難になるため、少し残念ですgen_serverterminate/2また、システムのデバッグを困難にする他の多くのエラーをキャッチする可能性があるため、実行できるようにするためだけに出口をトラップすることは良い習慣ではありません。

私は3つのオプションを検討します:

  1. プロセスの次のインスタンスが開始するときに、残ったファイルを処理します(たとえば、init/1
  2. トラップが終了し、ファイルをクリーンアップしてから、同じ理由で再度クラッシュします
  3. gen_serverファイルをクリーンアップすることだけを目的とする監視を行う3番目のプロセスを用意します

少なくともコードは出口をトラップせず、永続的な状態を無料で取得できるため、オプション1がおそらく最良のオプションです。オプション2は、上記の理由であまり良くないため、他のエラーを隠したり覆い隠したりする可能性があります。gen_server3は、が再開される前にクリーンアッププロセスが実行されない可能性があるため、面倒です。

クリーンアップする理由と、プロセスがクラッシュしたときに本当にクリーンアップする必要があるかどうかを慎重に検討してください(結局のところ、これはバグです)。防御的なプログラミングをやりすぎないように注意してください。

于 2011-02-25T15:49:24.723 に答える
0

これは非常に新鮮で関連性 があります。terminate/2 が gen_server で呼び出されるのはいつですか?

于 2016-06-24T01:39:29.207 に答える