在关闭的 unix 套接字上杀死 socket.accept() 调用 [英] kill socket.accept() call on closed unix socket

查看:116
本文介绍了在关闭的 unix 套接字上杀死 socket.accept() 调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Socket.close() 不会停止任何已经在该套接字上运行的阻塞性 socket.accept() 调用.

Socket.close() does not stop any blocking socket.accept() calls that are already running on that socket.

我的 python 程序中有几个线程只在已经关闭的 unix 域套接字上运行阻塞 socket.accept() 调用.我想通过使 socket.accept() 调用停止或引发异常.

I have several threads in my python program that only run a blocking socket.accept() call on a unix domain socket that has been closed already. I want to kill these threads by making the socket.accept() calls stop or raise an exception.

我试图通过在程序中加载新代码而不停止程序来做到这一点.因此,不能更改产生这些线程或关闭套接字的代码.

I am trying to do this by loading new code in the program, without stopping the program. Therefore, changing the code that spawned these threads or that closed the sockets is not an option.

有没有办法做到这一点?

Is there any way to do this?

这类似于 https://stackoverflow.com/a/10090348/3084431,但这些解决方案不起作用对于我的代码:

This is similar to https://stackoverflow.com/a/10090348/3084431, but these solutions wont work for my code:

  1. 这一点是不正确的,关闭不会在接受时引发异常.关闭可以,但是当线程关闭时就不能再调用了.
  2. 我无法再连接到此套接字.套接字已关闭.
  3. 接受调用的线程已经在运行,我无法更改它们.
  4. 同3

为了澄清起见,我写了一些有这个问题的示例代码.此代码适用于 python 2 和 python 3.

For clarification, I have written some example code that has this problem. This code works in both python 2 and python 3.

import socket
import threading
import time

address = "./socket.sock"

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(address)
sock.listen(5)

def accept():
    print(sock.accept())

t = threading.Thread(target=accept, name="acceptorthread")
t.start()

sock.close()

time.sleep(0.5) # give the thread some time to register the closing

print(threading.enumerate()) # the acceptorthread will still be running

我需要的是在这段代码完成后我可以运行的东西,它可以以某种方式停止接受者线程.

What I need is something that I can run after this code has finished that can stop the acceptor thread somehow.

推荐答案

内核中没有机制来通知每个侦听器套接字已关闭.你必须自己写一些东西.一个简单的解决方案是在套接字上使用超时:

There is no mechanism in kernel to notify every listener that a socket is closed. You have to write something yourself. A simple solution is to use timeout on socket:

sock.settimeout(1)

def accept():
    while True:
        try:
            print(sock.accept())
        except socket.timeout:
            continue
        break

现在,当您关闭套接字时,对 .accept() 的下一次调用(超时后)将抛出错误描述符"异常.

Now when you close the socket the next call (after a timeout) to .accept() will throw a "bad descriptor" exception.

还要记住 Python 中的 sockets api 不是线程安全的.建议在多线程环境中使用锁(或其他同步方法)包装每个套接字调用.

Also remember that sockets api in Python is not thread safe. Wrapping every socket call with a lock (or other synchronization methods) is advised in multi-threaded environment.

更高级(更高效)的是使用 select 调用来包装您的套接字.请注意,套接字不必处于非阻塞模式才能使用它.

More advanced (and efficient) would be to use wrap your socket with a select call. Note that the socket does not have to be in non-blocking mode in order to use it.

因此,不能更改产生这些线程或关闭套接字的代码.

Therefore, changing the code that spawned these threads or that closed the sockets is not an option.

如果真是这样,那你就完蛋了.不改变在线程中运行的代码是不可能实现的.这就像问如何在不改装汽车的情况下修理我的坏车".不会发生的,伙计.

If that's the case, then you are doomed. Without changing the code running in threads it is impossible to achieve. It's like asking "how can I fix my broken car without modifying the car". Won't happen, mate.

这篇关于在关闭的 unix 套接字上杀死 socket.accept() 调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆