issue #155: introduce mitogen.fork / Router.fork()
parent
db1b5f7d62
commit
1a8ac9f4d1
@ -0,0 +1,98 @@
|
||||
# Copyright 2017, David Wilson
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import threading
|
||||
|
||||
import mitogen.core
|
||||
import mitogen.parent
|
||||
|
||||
|
||||
LOG = logging.getLogger('mitogen')
|
||||
|
||||
|
||||
def break_logging_locks():
|
||||
"""
|
||||
After fork, ensure any logging.Handler locks are recreated, as a variety of
|
||||
threads in the parent may have been using the logging package at the moment
|
||||
of fork.
|
||||
|
||||
It is not possible to solve this problem in general; see
|
||||
https://github.com/dw/mitogen/issues/150 for a full discussion.
|
||||
"""
|
||||
logging._lock = threading.RLock()
|
||||
for name in logging.Logger.manager.loggerDict:
|
||||
for handler in logging.getLogger(name).handlers:
|
||||
handler.createLock()
|
||||
|
||||
|
||||
class Stream(mitogen.parent.Stream):
|
||||
#: Reference to the importer, if any, recovered from the parent.
|
||||
importer = None
|
||||
|
||||
def construct(self, old_router, debug=False, profiling=False):
|
||||
# fork method only supports a tiny subset of options.
|
||||
super(Stream, self).construct(debug=debug, profiling=profiling)
|
||||
|
||||
responder = getattr(old_router, 'responder', None)
|
||||
if isinstance(responder, mitogen.parent.ModuleForwarder):
|
||||
self.importer = responder.importer
|
||||
|
||||
def create_child(self, *_args):
|
||||
parentfp, childfp = mitogen.parent.create_socketpair()
|
||||
self.pid = os.fork()
|
||||
if self.pid:
|
||||
childfp.close()
|
||||
# Decouple the socket from the lifetime of the Python socket object.
|
||||
fd = os.dup(parentfp.fileno())
|
||||
parentfp.close()
|
||||
return self.pid, fd
|
||||
else:
|
||||
parentfp.close()
|
||||
self._child_main(childfp)
|
||||
|
||||
def _child_main(self, childfp):
|
||||
break_logging_locks()
|
||||
mitogen.core.set_block(childfp.fileno())
|
||||
os.dup2(childfp.fileno(), 1)
|
||||
os.dup2(childfp.fileno(), 100)
|
||||
kwargs = self.get_main_kwargs()
|
||||
kwargs['core_src_fd'] = None
|
||||
kwargs['importer'] = self.importer
|
||||
kwargs['setup_package'] = False
|
||||
mitogen.core.ExternalContext().main(**kwargs)
|
||||
sys.exit(0)
|
||||
|
||||
def connect(self):
|
||||
super(Stream, self).connect()
|
||||
self.name = 'fork.' + str(self.pid)
|
||||
|
||||
def _connect_bootstrap(self):
|
||||
# None required.
|
||||
pass
|
Loading…
Reference in New Issue