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