2017-08-21 5 views
1

バックエンドが実行されていないときにこの問題に遭遇しました。
あなたがここに私の場合を再現するために、本当に簡単なデモを見つけることができます(あなたには、いくつかの時間のテストを保存したい場合は、1にタイムアウトを減らすことができます):aiozmq/zmqを正しく閉じるには?

#!/usr/bin/env python3 

import threading 
import logging 
import asyncio 
from aiozmq import rpc 

logging.getLogger().setLevel(logging.DEBUG) 

async def go(): 
    logging.debug('Go !') 
    client = None 
    try: 
     client = await rpc.connect_rpc(connect='tcp://127.0.0.1:5555', timeout=5) 
     await client.call.remote(1, 2) 
    except Exception as e: 
     logging.exception(e) 
    finally: 
     if client is not None: 
      client.close() 
      await client.wait_closed() 

    logging.debug('done') 

loop = asyncio.get_event_loop() 
loop.run_until_complete(go()) 
loop.close() 

logging.debug(asyncio.Task.all_tasks()) 
logging.debug(threading.enumerate()) 

あなたはそのコロの両方に気付くでしょう(go & 1私たちwait_for)が実行され、pythonはMainThreadだけを追跡します。
しかし、上に(htop)あなたのスクリプトは実際には2スレッド実行していることがわかります。私は100%確実ではないが、私たちが受け取るEPOLLOUT|EPOLLERR|EPOLLHUPは= HUP =ハングアップだと思う

 
epoll_wait(13, [], 256, 168)   = 0 
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 
fcntl(3, F_SETFD, FD_CLOEXEC)   = 0 
fcntl(3, F_GETFL)      = 0x2 (flags O_RDWR) 
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 
connect(3, {sa_family=AF_INET, sin_port=htons(5555), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) 
epoll_ctl(13, EPOLL_CTL_ADD, 3, {0, {u32=1275071824, u64=140476770422096}}) = 0 
epoll_ctl(13, EPOLL_CTL_MOD, 3, {EPOLLOUT, {u32=1275071824, u64=140476770422096}}) = 0 
epoll_wait(13, [{EPOLLOUT|EPOLLERR|EPOLLHUP, {u32=1275071824, u64=140476770422096}}], 256, -1) = 1 
epoll_ctl(13, EPOLL_CTL_DEL, 3, 0x7fc34c000d54) = 0 
getsockopt(3, SOL_SOCKET, SO_ERROR, [111], [4]) = 0 
close(3)        = 0 

:ルーピングepoll_wait(10,

  • 1にブロックされ

    • 1接続拒否。

      残りの/不可視のスレッドをzmqライブラリのどこかに追跡しました。

      誰が何が起こっているのか、どのように正しく停止しているかを知っていますか?

  • 答えて

    0

    また、これをgithubのissueとして投稿し、答えを得ました。

    これは実際にLinger periodが原因です。

    解決策は、connect_rpcの呼び出しの直後にclient.transport.setsockopt(zmq.LINGER, 0)を追加することです。


    また、(これは例えば、別の例外に)ループがもはや実行されていない場合、ソケットを閉じることで、任意の試みを防止するために閉じるfinallyifloop.is_running()を追加することが有用であり得ます。

    関連する問題