web-dev-qa-db-ja.com

zmq.error.ZMQErrorからの回復:アドレスはすでに使用されています

ZMQでPAIRパターン(非ブロッキングクライアントサーバー)接続を実行しているときにCtrl-Cを押しました。後でREQ-REP(クライアントの単一サーバー接続をブロックする)パターンを実行しようとすると、Address already in useエラーが発生し続けます。 netstat -ltnp | grep :<my port>でnetstatを実行しようとしましたが、プロセスがリストされていません。

では、誰がこのアドレスを正確に使用しているのでしょうか。

また、これらのようなソケット接続をどのように正常にシャットダウンしますか?

16

質問1:

LinuxタイプのオペレーティングシステムでSudo netstat -ltnpを実行すると、おそらくプロセスがポートを所有していることがわかります。 kill -9 <pid>で殺します。

質問2:

プログラムを終了したら、ソケットを閉じてからzmq_ctx_destroy()を呼び出します。これにより、コンテキストが破壊されます。詳細については、 http://zguide.zeromq.org/page:all#toc17 を参照してください。

21
jorgen

今この瞬間に:

_reboot
_

次:

_try:_/_except:_/_finally:_カプセル化コンストラクターの使用を開始します。これは、すべてのzmq割り当てから正常な終了を許可するを支援します。 allSocket-s'.close() andContext.term()は、非常ボタンまたは未処理の例外がコード実行を完全に中断し、まだハングしているネットワークハードウェアバウンドへの参照を失った場合でも、孤立した孤立したメモリリークが発生することはありません、インスタンス。

3
user3666197

別のzeromqを使用するプロセスがポートを使用し続けている場合があり、netstatは他のプロセスがリッスンしていることを示しません(したがって、netstat -lntpは表示されません)が、両端に同じホスト/ポートを持つポートで確立された接続を表示します。他のプロセスを強制終了すると、ポートを使用できるようになります。

理由#1:発信接続のローカル側として使用されるエフェメラルポート(Linuxの場合は32768-61000など)の範囲にzeromqリスニングポートを設定し、サービスを接続する必要があるため、これが発生しました同じボックス上の他のサービスに。発信接続がボックスのリスニングポートと同じエフェメラルポートを取得し、突然「アドレスがすでに使用されている」場合の割合。すべてのリスニングポートをエフェメラルポート範囲の邪魔にならない場所に移動したところ、「アドレスはすでに使用されています」という問題はすべて解消されました。

理由#2:推測:他のpythonネットワークライブラリで同様の問題が発生した場合、問題のプロセスは以前にサブプロセスなどを使用してリスニングプロセスから起動され、問題が発生しました。ソケットが子プロセスにリークしています。親プロセスがソケットを閉じずに終了した場合、ソケットは存続し、子プロセスによって所有されます。子プロセスはソケットについて何も知らなかったとしても、それでも他のプロセスがそれを使用できないように持ちこたえました。

それが問題である場合は、サブプロセスの前にソケットのフラグを微調整することで修正できる可能性があります。 (UNIX固有):

fd = sock.get(zmq.FD)
old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)

または、親プロセスのソケットをより適切に閉じる方法があるかもしれません。

2
rakslice