1

次のプログラムを作成しようとしています。

  • 使い始めのフォークmultiprocessing
  • フォークされたプロセスはpython-daemon、バックグラウンドで再びフォークするために使用します
  • 結果として生じるバックグラウンド プロセスで、ねじれたリッスン TCP ポートを開く

起動する前にプロセスをフォークする必要があるのpython-daemonは、スターしているプロセスを存続させたいためです (デフォルトでは、親プロセスを強制終了python-daemonします)。

これまでのところ、私のコードは次のとおりです。

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()

プロセスを開始するとうまくいくようです:

INFO:client:ClientPart.__init__()
INFO:client:launch_daemon()
INFO:server:ServerPart.__init__()
INFO:server:start_second_daemon()

しかし、バックグラウンド プロセスのログ ファイルを見ると、twisted は TCP ポートを開くことができません。

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が開始されたときに、バックグラウンド プロセスのすべてのファイル記述子を閉じているようですが、この動作が原因でしょうか?

4

1 に答える 1

1

fork を実行してから、動作しない任意のライブラリ コードを実行する理由はたくさんあります。それらをすべてここにリストするのは難しいでしょうが、一般的にはそうするのはクールではありません。ここで具体的に何が起こっているかについての私の推測では、multiprocessingTwisted がそのスレッド プールと通信できるようにする「ウェイカー」ファイル記述子を何かが閉じているということですが、完全には確信が持てません。

これを次のように書き換える場合:

  1. spawnProcessの代わりに使用multiprocessing
  2. twistdの代わりに使用python-daemonize

多くの偶発的なプラットフォームの相互作用 (fork の呼び出し、pickle によるパイプを介した物事のシリアル化、setsid の呼び出し) を伴う 2 つのことの代わりに、Twisted で動作するように特別に設計されたプロセスの生成とデーモン化のコードを使用するため、相互作用はそれほど驚くべきことではありません。 setuid を実行し、制御端末とセッション リーダーをさまざまな時点で変更します)。

upstart(そして実際には、またはlaunchdまたはsystemdクロスプラットフォームのようrunitなプラットフォームのデーモン管理ツールと統合することをお勧めしますtwistd。お勧め。)

于 2013-10-08T23:11:55.677 に答える