首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用python-daemon侦听Twisted TCP连接会给出错误的文件描述符。

使用python-daemon侦听Twisted TCP连接会给出错误的文件描述符。
EN

Stack Overflow用户
提问于 2013-10-08 21:40:18
回答 1查看 871关注 0票数 1

我正在尝试创建一个程序:

  • 使用multiprocessing启动分叉
  • 分叉进程在后台使用python-daemon再次分叉。
  • 在生成的后台进程中打开扭曲的侦听TCP端口。

在启动python-daemon之前,我需要对进程进行分叉,因为我希望凝视进程保持活跃(默认情况下,python-daemon会杀死父进程)。

到目前为止,我的代码是:

代码语言:javascript
复制
from twisted.web import xmlrpc, server
from twisted.internet import reactor
from daemon import daemon
import multiprocessing
import os
import logging

class RemotePart(object):

    def setup(self):
        self.commands = CommandPart()
        reactor.listenTCP(9091, server.Site(self.commands))

class CommandPart(xmlrpc.XMLRPC, object):

    def __init__(self):
        super(CommandPart, self).__init__()

    def xmlrpc_stop(self):
        return True


class ServerPart(object):

    def __init__(self):
        self.logger = logging.getLogger("server")
        self.logger.info("ServerPart.__init__()")

    def start_second_daemon(self):
        self.logger.info("start_second_daemon()")        
        daemon_context = daemon.DaemonContext(detach_process=True)
        daemon_context.stdout = open(
            name="log.txt", 
            mode='w+', 
            buffering=0
        )
        daemon_context.stderr = open(
            name="log.txt", 
            mode='w+', 
            buffering=0
        )
        daemon_context.working_directory = os.getcwd()

        daemon_context.open()
        self.inside_daemon()

    def inside_daemon(self):
        self.logger.setLevel(0)
        self.logger.info("inside daemon")
        self.remote = RemotePart()
        self.remote.setup()
        reactor.run()

class ClientPart(object):

    def __init__(self):
        logging.basicConfig(level=0)
        self.logger = logging.getLogger("client")
        self.logger.info("ClientPart.__init__()")

    def start_daemon(self):
        self.logger.info("start_daemon()")
        start_second_daemon()

    def launch_daemon(self):
        self.logger.info("launch_daemon()")
        server = ServerPart()
        p = multiprocessing.Process(target=server.start_second_daemon())
        p.start()
        p.join()

if __name__ == '__main__':
    client = ClientPart()
    client.launch_daemon()

启动这一进程似乎是可行的:

代码语言:javascript
复制
INFO:client:ClientPart.__init__()
INFO:client:launch_daemon()
INFO:server:ServerPart.__init__()
INFO:server:start_second_daemon()

但是,查看后台进程的日志文件,扭曲无法打开TCP端口:

代码语言:javascript
复制
INFO:server:inside daemon
Traceback (most recent call last):
  File "forking_test.py", line 74, in <module>
    client.launch_daemon()
  File "forking_test.py", line 68, in launch_daemon
    p = multiprocessing.Process(target=server.start_second_daemon())
  File "forking_test.py", line 45, in start_second_daemon
    self.inside_daemon()
  File "forking_test.py", line 51, in inside_daemon
    self.remote.setup()
  File "forking_test.py", line 12, in setup
    reactor.listenTCP(9091, server.Site(self.commands))
  File "/usr/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 482, in listenTCP
    p.startListening()
  File "/usr/lib/python2.7/site-packages/twisted/internet/tcp.py", line 1004, in startListening
    self.startReading()
  File "/usr/lib/python2.7/site-packages/twisted/internet/abstract.py", line 429, in startReading
    self.reactor.addReader(self)
  File "/usr/lib/python2.7/site-packages/twisted/internet/epollreactor.py", line 247, in addReader
    EPOLLIN, EPOLLOUT)
  File "/usr/lib/python2.7/site-packages/twisted/internet/epollreactor.py", line 233, in _add
    self._poller.register(fd, flags)
IOError: [Errno 9] Bad file descriptor

知道吗?当后台进程启动时,python-daemon似乎正在关闭所有文件描述符,它是否来自此行为?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-08 23:11:55

运行叉子,然后运行一些不起作用的任意库代码有很多原因。在这里很难把它们全部列出来,但一般来说,这样做并不酷。我对这里具体发生的事情的猜测是,multiprocessing中的某些东西正在关闭"waker“文件描述符,该描述符允许Twisted与其线程池进行通信,但我不能完全确定。

如果你要把这个改写成:

  1. 使用spawnProcess而不是multiprocessing
  2. 使用twistd而不是python-daemonize

这样的交互就不会那么令人惊讶了,因为您将使用专门为使用Twisted而设计的进程生成和守护代码,而不是使用大量偶然的平台交互(调用叉、用泡菜在管道上串行化、调用setsid和setuid以及在不同时间更改控制终端和会话领导者)。

(实际上,我建议集成平台的守护进程管理工具,比如upstartlaunchdsystemd,或者像runit这样的跨平台管理工具,而不是依赖于任何守护代码,包括twistd中的守护进程管理工具,但我需要更多地了解您的应用程序,才能知道应该推荐什么。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19258972

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档