xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/multiprocessing/context.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Workerimport os
2*cda5da8dSAndroid Build Coastguard Workerimport sys
3*cda5da8dSAndroid Build Coastguard Workerimport threading
4*cda5da8dSAndroid Build Coastguard Worker
5*cda5da8dSAndroid Build Coastguard Workerfrom . import process
6*cda5da8dSAndroid Build Coastguard Workerfrom . import reduction
7*cda5da8dSAndroid Build Coastguard Worker
8*cda5da8dSAndroid Build Coastguard Worker__all__ = ()
9*cda5da8dSAndroid Build Coastguard Worker
10*cda5da8dSAndroid Build Coastguard Worker#
11*cda5da8dSAndroid Build Coastguard Worker# Exceptions
12*cda5da8dSAndroid Build Coastguard Worker#
13*cda5da8dSAndroid Build Coastguard Worker
14*cda5da8dSAndroid Build Coastguard Workerclass ProcessError(Exception):
15*cda5da8dSAndroid Build Coastguard Worker    pass
16*cda5da8dSAndroid Build Coastguard Worker
17*cda5da8dSAndroid Build Coastguard Workerclass BufferTooShort(ProcessError):
18*cda5da8dSAndroid Build Coastguard Worker    pass
19*cda5da8dSAndroid Build Coastguard Worker
20*cda5da8dSAndroid Build Coastguard Workerclass TimeoutError(ProcessError):
21*cda5da8dSAndroid Build Coastguard Worker    pass
22*cda5da8dSAndroid Build Coastguard Worker
23*cda5da8dSAndroid Build Coastguard Workerclass AuthenticationError(ProcessError):
24*cda5da8dSAndroid Build Coastguard Worker    pass
25*cda5da8dSAndroid Build Coastguard Worker
26*cda5da8dSAndroid Build Coastguard Worker#
27*cda5da8dSAndroid Build Coastguard Worker# Base type for contexts. Bound methods of an instance of this type are included in __all__ of __init__.py
28*cda5da8dSAndroid Build Coastguard Worker#
29*cda5da8dSAndroid Build Coastguard Worker
30*cda5da8dSAndroid Build Coastguard Workerclass BaseContext(object):
31*cda5da8dSAndroid Build Coastguard Worker
32*cda5da8dSAndroid Build Coastguard Worker    ProcessError = ProcessError
33*cda5da8dSAndroid Build Coastguard Worker    BufferTooShort = BufferTooShort
34*cda5da8dSAndroid Build Coastguard Worker    TimeoutError = TimeoutError
35*cda5da8dSAndroid Build Coastguard Worker    AuthenticationError = AuthenticationError
36*cda5da8dSAndroid Build Coastguard Worker
37*cda5da8dSAndroid Build Coastguard Worker    current_process = staticmethod(process.current_process)
38*cda5da8dSAndroid Build Coastguard Worker    parent_process = staticmethod(process.parent_process)
39*cda5da8dSAndroid Build Coastguard Worker    active_children = staticmethod(process.active_children)
40*cda5da8dSAndroid Build Coastguard Worker
41*cda5da8dSAndroid Build Coastguard Worker    def cpu_count(self):
42*cda5da8dSAndroid Build Coastguard Worker        '''Returns the number of CPUs in the system'''
43*cda5da8dSAndroid Build Coastguard Worker        num = os.cpu_count()
44*cda5da8dSAndroid Build Coastguard Worker        if num is None:
45*cda5da8dSAndroid Build Coastguard Worker            raise NotImplementedError('cannot determine number of cpus')
46*cda5da8dSAndroid Build Coastguard Worker        else:
47*cda5da8dSAndroid Build Coastguard Worker            return num
48*cda5da8dSAndroid Build Coastguard Worker
49*cda5da8dSAndroid Build Coastguard Worker    def Manager(self):
50*cda5da8dSAndroid Build Coastguard Worker        '''Returns a manager associated with a running server process
51*cda5da8dSAndroid Build Coastguard Worker
52*cda5da8dSAndroid Build Coastguard Worker        The managers methods such as `Lock()`, `Condition()` and `Queue()`
53*cda5da8dSAndroid Build Coastguard Worker        can be used to create shared objects.
54*cda5da8dSAndroid Build Coastguard Worker        '''
55*cda5da8dSAndroid Build Coastguard Worker        from .managers import SyncManager
56*cda5da8dSAndroid Build Coastguard Worker        m = SyncManager(ctx=self.get_context())
57*cda5da8dSAndroid Build Coastguard Worker        m.start()
58*cda5da8dSAndroid Build Coastguard Worker        return m
59*cda5da8dSAndroid Build Coastguard Worker
60*cda5da8dSAndroid Build Coastguard Worker    def Pipe(self, duplex=True):
61*cda5da8dSAndroid Build Coastguard Worker        '''Returns two connection object connected by a pipe'''
62*cda5da8dSAndroid Build Coastguard Worker        from .connection import Pipe
63*cda5da8dSAndroid Build Coastguard Worker        return Pipe(duplex)
64*cda5da8dSAndroid Build Coastguard Worker
65*cda5da8dSAndroid Build Coastguard Worker    def Lock(self):
66*cda5da8dSAndroid Build Coastguard Worker        '''Returns a non-recursive lock object'''
67*cda5da8dSAndroid Build Coastguard Worker        from .synchronize import Lock
68*cda5da8dSAndroid Build Coastguard Worker        return Lock(ctx=self.get_context())
69*cda5da8dSAndroid Build Coastguard Worker
70*cda5da8dSAndroid Build Coastguard Worker    def RLock(self):
71*cda5da8dSAndroid Build Coastguard Worker        '''Returns a recursive lock object'''
72*cda5da8dSAndroid Build Coastguard Worker        from .synchronize import RLock
73*cda5da8dSAndroid Build Coastguard Worker        return RLock(ctx=self.get_context())
74*cda5da8dSAndroid Build Coastguard Worker
75*cda5da8dSAndroid Build Coastguard Worker    def Condition(self, lock=None):
76*cda5da8dSAndroid Build Coastguard Worker        '''Returns a condition object'''
77*cda5da8dSAndroid Build Coastguard Worker        from .synchronize import Condition
78*cda5da8dSAndroid Build Coastguard Worker        return Condition(lock, ctx=self.get_context())
79*cda5da8dSAndroid Build Coastguard Worker
80*cda5da8dSAndroid Build Coastguard Worker    def Semaphore(self, value=1):
81*cda5da8dSAndroid Build Coastguard Worker        '''Returns a semaphore object'''
82*cda5da8dSAndroid Build Coastguard Worker        from .synchronize import Semaphore
83*cda5da8dSAndroid Build Coastguard Worker        return Semaphore(value, ctx=self.get_context())
84*cda5da8dSAndroid Build Coastguard Worker
85*cda5da8dSAndroid Build Coastguard Worker    def BoundedSemaphore(self, value=1):
86*cda5da8dSAndroid Build Coastguard Worker        '''Returns a bounded semaphore object'''
87*cda5da8dSAndroid Build Coastguard Worker        from .synchronize import BoundedSemaphore
88*cda5da8dSAndroid Build Coastguard Worker        return BoundedSemaphore(value, ctx=self.get_context())
89*cda5da8dSAndroid Build Coastguard Worker
90*cda5da8dSAndroid Build Coastguard Worker    def Event(self):
91*cda5da8dSAndroid Build Coastguard Worker        '''Returns an event object'''
92*cda5da8dSAndroid Build Coastguard Worker        from .synchronize import Event
93*cda5da8dSAndroid Build Coastguard Worker        return Event(ctx=self.get_context())
94*cda5da8dSAndroid Build Coastguard Worker
95*cda5da8dSAndroid Build Coastguard Worker    def Barrier(self, parties, action=None, timeout=None):
96*cda5da8dSAndroid Build Coastguard Worker        '''Returns a barrier object'''
97*cda5da8dSAndroid Build Coastguard Worker        from .synchronize import Barrier
98*cda5da8dSAndroid Build Coastguard Worker        return Barrier(parties, action, timeout, ctx=self.get_context())
99*cda5da8dSAndroid Build Coastguard Worker
100*cda5da8dSAndroid Build Coastguard Worker    def Queue(self, maxsize=0):
101*cda5da8dSAndroid Build Coastguard Worker        '''Returns a queue object'''
102*cda5da8dSAndroid Build Coastguard Worker        from .queues import Queue
103*cda5da8dSAndroid Build Coastguard Worker        return Queue(maxsize, ctx=self.get_context())
104*cda5da8dSAndroid Build Coastguard Worker
105*cda5da8dSAndroid Build Coastguard Worker    def JoinableQueue(self, maxsize=0):
106*cda5da8dSAndroid Build Coastguard Worker        '''Returns a queue object'''
107*cda5da8dSAndroid Build Coastguard Worker        from .queues import JoinableQueue
108*cda5da8dSAndroid Build Coastguard Worker        return JoinableQueue(maxsize, ctx=self.get_context())
109*cda5da8dSAndroid Build Coastguard Worker
110*cda5da8dSAndroid Build Coastguard Worker    def SimpleQueue(self):
111*cda5da8dSAndroid Build Coastguard Worker        '''Returns a queue object'''
112*cda5da8dSAndroid Build Coastguard Worker        from .queues import SimpleQueue
113*cda5da8dSAndroid Build Coastguard Worker        return SimpleQueue(ctx=self.get_context())
114*cda5da8dSAndroid Build Coastguard Worker
115*cda5da8dSAndroid Build Coastguard Worker    def Pool(self, processes=None, initializer=None, initargs=(),
116*cda5da8dSAndroid Build Coastguard Worker             maxtasksperchild=None):
117*cda5da8dSAndroid Build Coastguard Worker        '''Returns a process pool object'''
118*cda5da8dSAndroid Build Coastguard Worker        from .pool import Pool
119*cda5da8dSAndroid Build Coastguard Worker        return Pool(processes, initializer, initargs, maxtasksperchild,
120*cda5da8dSAndroid Build Coastguard Worker                    context=self.get_context())
121*cda5da8dSAndroid Build Coastguard Worker
122*cda5da8dSAndroid Build Coastguard Worker    def RawValue(self, typecode_or_type, *args):
123*cda5da8dSAndroid Build Coastguard Worker        '''Returns a shared object'''
124*cda5da8dSAndroid Build Coastguard Worker        from .sharedctypes import RawValue
125*cda5da8dSAndroid Build Coastguard Worker        return RawValue(typecode_or_type, *args)
126*cda5da8dSAndroid Build Coastguard Worker
127*cda5da8dSAndroid Build Coastguard Worker    def RawArray(self, typecode_or_type, size_or_initializer):
128*cda5da8dSAndroid Build Coastguard Worker        '''Returns a shared array'''
129*cda5da8dSAndroid Build Coastguard Worker        from .sharedctypes import RawArray
130*cda5da8dSAndroid Build Coastguard Worker        return RawArray(typecode_or_type, size_or_initializer)
131*cda5da8dSAndroid Build Coastguard Worker
132*cda5da8dSAndroid Build Coastguard Worker    def Value(self, typecode_or_type, *args, lock=True):
133*cda5da8dSAndroid Build Coastguard Worker        '''Returns a synchronized shared object'''
134*cda5da8dSAndroid Build Coastguard Worker        from .sharedctypes import Value
135*cda5da8dSAndroid Build Coastguard Worker        return Value(typecode_or_type, *args, lock=lock,
136*cda5da8dSAndroid Build Coastguard Worker                     ctx=self.get_context())
137*cda5da8dSAndroid Build Coastguard Worker
138*cda5da8dSAndroid Build Coastguard Worker    def Array(self, typecode_or_type, size_or_initializer, *, lock=True):
139*cda5da8dSAndroid Build Coastguard Worker        '''Returns a synchronized shared array'''
140*cda5da8dSAndroid Build Coastguard Worker        from .sharedctypes import Array
141*cda5da8dSAndroid Build Coastguard Worker        return Array(typecode_or_type, size_or_initializer, lock=lock,
142*cda5da8dSAndroid Build Coastguard Worker                     ctx=self.get_context())
143*cda5da8dSAndroid Build Coastguard Worker
144*cda5da8dSAndroid Build Coastguard Worker    def freeze_support(self):
145*cda5da8dSAndroid Build Coastguard Worker        '''Check whether this is a fake forked process in a frozen executable.
146*cda5da8dSAndroid Build Coastguard Worker        If so then run code specified by commandline and exit.
147*cda5da8dSAndroid Build Coastguard Worker        '''
148*cda5da8dSAndroid Build Coastguard Worker        if sys.platform == 'win32' and getattr(sys, 'frozen', False):
149*cda5da8dSAndroid Build Coastguard Worker            from .spawn import freeze_support
150*cda5da8dSAndroid Build Coastguard Worker            freeze_support()
151*cda5da8dSAndroid Build Coastguard Worker
152*cda5da8dSAndroid Build Coastguard Worker    def get_logger(self):
153*cda5da8dSAndroid Build Coastguard Worker        '''Return package logger -- if it does not already exist then
154*cda5da8dSAndroid Build Coastguard Worker        it is created.
155*cda5da8dSAndroid Build Coastguard Worker        '''
156*cda5da8dSAndroid Build Coastguard Worker        from .util import get_logger
157*cda5da8dSAndroid Build Coastguard Worker        return get_logger()
158*cda5da8dSAndroid Build Coastguard Worker
159*cda5da8dSAndroid Build Coastguard Worker    def log_to_stderr(self, level=None):
160*cda5da8dSAndroid Build Coastguard Worker        '''Turn on logging and add a handler which prints to stderr'''
161*cda5da8dSAndroid Build Coastguard Worker        from .util import log_to_stderr
162*cda5da8dSAndroid Build Coastguard Worker        return log_to_stderr(level)
163*cda5da8dSAndroid Build Coastguard Worker
164*cda5da8dSAndroid Build Coastguard Worker    def allow_connection_pickling(self):
165*cda5da8dSAndroid Build Coastguard Worker        '''Install support for sending connections and sockets
166*cda5da8dSAndroid Build Coastguard Worker        between processes
167*cda5da8dSAndroid Build Coastguard Worker        '''
168*cda5da8dSAndroid Build Coastguard Worker        # This is undocumented.  In previous versions of multiprocessing
169*cda5da8dSAndroid Build Coastguard Worker        # its only effect was to make socket objects inheritable on Windows.
170*cda5da8dSAndroid Build Coastguard Worker        from . import connection
171*cda5da8dSAndroid Build Coastguard Worker
172*cda5da8dSAndroid Build Coastguard Worker    def set_executable(self, executable):
173*cda5da8dSAndroid Build Coastguard Worker        '''Sets the path to a python.exe or pythonw.exe binary used to run
174*cda5da8dSAndroid Build Coastguard Worker        child processes instead of sys.executable when using the 'spawn'
175*cda5da8dSAndroid Build Coastguard Worker        start method.  Useful for people embedding Python.
176*cda5da8dSAndroid Build Coastguard Worker        '''
177*cda5da8dSAndroid Build Coastguard Worker        from .spawn import set_executable
178*cda5da8dSAndroid Build Coastguard Worker        set_executable(executable)
179*cda5da8dSAndroid Build Coastguard Worker
180*cda5da8dSAndroid Build Coastguard Worker    def set_forkserver_preload(self, module_names):
181*cda5da8dSAndroid Build Coastguard Worker        '''Set list of module names to try to load in forkserver process.
182*cda5da8dSAndroid Build Coastguard Worker        This is really just a hint.
183*cda5da8dSAndroid Build Coastguard Worker        '''
184*cda5da8dSAndroid Build Coastguard Worker        from .forkserver import set_forkserver_preload
185*cda5da8dSAndroid Build Coastguard Worker        set_forkserver_preload(module_names)
186*cda5da8dSAndroid Build Coastguard Worker
187*cda5da8dSAndroid Build Coastguard Worker    def get_context(self, method=None):
188*cda5da8dSAndroid Build Coastguard Worker        if method is None:
189*cda5da8dSAndroid Build Coastguard Worker            return self
190*cda5da8dSAndroid Build Coastguard Worker        try:
191*cda5da8dSAndroid Build Coastguard Worker            ctx = _concrete_contexts[method]
192*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
193*cda5da8dSAndroid Build Coastguard Worker            raise ValueError('cannot find context for %r' % method) from None
194*cda5da8dSAndroid Build Coastguard Worker        ctx._check_available()
195*cda5da8dSAndroid Build Coastguard Worker        return ctx
196*cda5da8dSAndroid Build Coastguard Worker
197*cda5da8dSAndroid Build Coastguard Worker    def get_start_method(self, allow_none=False):
198*cda5da8dSAndroid Build Coastguard Worker        return self._name
199*cda5da8dSAndroid Build Coastguard Worker
200*cda5da8dSAndroid Build Coastguard Worker    def set_start_method(self, method, force=False):
201*cda5da8dSAndroid Build Coastguard Worker        raise ValueError('cannot set start method of concrete context')
202*cda5da8dSAndroid Build Coastguard Worker
203*cda5da8dSAndroid Build Coastguard Worker    @property
204*cda5da8dSAndroid Build Coastguard Worker    def reducer(self):
205*cda5da8dSAndroid Build Coastguard Worker        '''Controls how objects will be reduced to a form that can be
206*cda5da8dSAndroid Build Coastguard Worker        shared with other processes.'''
207*cda5da8dSAndroid Build Coastguard Worker        return globals().get('reduction')
208*cda5da8dSAndroid Build Coastguard Worker
209*cda5da8dSAndroid Build Coastguard Worker    @reducer.setter
210*cda5da8dSAndroid Build Coastguard Worker    def reducer(self, reduction):
211*cda5da8dSAndroid Build Coastguard Worker        globals()['reduction'] = reduction
212*cda5da8dSAndroid Build Coastguard Worker
213*cda5da8dSAndroid Build Coastguard Worker    def _check_available(self):
214*cda5da8dSAndroid Build Coastguard Worker        pass
215*cda5da8dSAndroid Build Coastguard Worker
216*cda5da8dSAndroid Build Coastguard Worker#
217*cda5da8dSAndroid Build Coastguard Worker# Type of default context -- underlying context can be set at most once
218*cda5da8dSAndroid Build Coastguard Worker#
219*cda5da8dSAndroid Build Coastguard Worker
220*cda5da8dSAndroid Build Coastguard Workerclass Process(process.BaseProcess):
221*cda5da8dSAndroid Build Coastguard Worker    _start_method = None
222*cda5da8dSAndroid Build Coastguard Worker    @staticmethod
223*cda5da8dSAndroid Build Coastguard Worker    def _Popen(process_obj):
224*cda5da8dSAndroid Build Coastguard Worker        return _default_context.get_context().Process._Popen(process_obj)
225*cda5da8dSAndroid Build Coastguard Worker
226*cda5da8dSAndroid Build Coastguard Worker    @staticmethod
227*cda5da8dSAndroid Build Coastguard Worker    def _after_fork():
228*cda5da8dSAndroid Build Coastguard Worker        return _default_context.get_context().Process._after_fork()
229*cda5da8dSAndroid Build Coastguard Worker
230*cda5da8dSAndroid Build Coastguard Workerclass DefaultContext(BaseContext):
231*cda5da8dSAndroid Build Coastguard Worker    Process = Process
232*cda5da8dSAndroid Build Coastguard Worker
233*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, context):
234*cda5da8dSAndroid Build Coastguard Worker        self._default_context = context
235*cda5da8dSAndroid Build Coastguard Worker        self._actual_context = None
236*cda5da8dSAndroid Build Coastguard Worker
237*cda5da8dSAndroid Build Coastguard Worker    def get_context(self, method=None):
238*cda5da8dSAndroid Build Coastguard Worker        if method is None:
239*cda5da8dSAndroid Build Coastguard Worker            if self._actual_context is None:
240*cda5da8dSAndroid Build Coastguard Worker                self._actual_context = self._default_context
241*cda5da8dSAndroid Build Coastguard Worker            return self._actual_context
242*cda5da8dSAndroid Build Coastguard Worker        else:
243*cda5da8dSAndroid Build Coastguard Worker            return super().get_context(method)
244*cda5da8dSAndroid Build Coastguard Worker
245*cda5da8dSAndroid Build Coastguard Worker    def set_start_method(self, method, force=False):
246*cda5da8dSAndroid Build Coastguard Worker        if self._actual_context is not None and not force:
247*cda5da8dSAndroid Build Coastguard Worker            raise RuntimeError('context has already been set')
248*cda5da8dSAndroid Build Coastguard Worker        if method is None and force:
249*cda5da8dSAndroid Build Coastguard Worker            self._actual_context = None
250*cda5da8dSAndroid Build Coastguard Worker            return
251*cda5da8dSAndroid Build Coastguard Worker        self._actual_context = self.get_context(method)
252*cda5da8dSAndroid Build Coastguard Worker
253*cda5da8dSAndroid Build Coastguard Worker    def get_start_method(self, allow_none=False):
254*cda5da8dSAndroid Build Coastguard Worker        if self._actual_context is None:
255*cda5da8dSAndroid Build Coastguard Worker            if allow_none:
256*cda5da8dSAndroid Build Coastguard Worker                return None
257*cda5da8dSAndroid Build Coastguard Worker            self._actual_context = self._default_context
258*cda5da8dSAndroid Build Coastguard Worker        return self._actual_context._name
259*cda5da8dSAndroid Build Coastguard Worker
260*cda5da8dSAndroid Build Coastguard Worker    def get_all_start_methods(self):
261*cda5da8dSAndroid Build Coastguard Worker        if sys.platform == 'win32':
262*cda5da8dSAndroid Build Coastguard Worker            return ['spawn']
263*cda5da8dSAndroid Build Coastguard Worker        else:
264*cda5da8dSAndroid Build Coastguard Worker            methods = ['spawn', 'fork'] if sys.platform == 'darwin' else ['fork', 'spawn']
265*cda5da8dSAndroid Build Coastguard Worker            if reduction.HAVE_SEND_HANDLE:
266*cda5da8dSAndroid Build Coastguard Worker                methods.append('forkserver')
267*cda5da8dSAndroid Build Coastguard Worker            return methods
268*cda5da8dSAndroid Build Coastguard Worker
269*cda5da8dSAndroid Build Coastguard Worker
270*cda5da8dSAndroid Build Coastguard Worker#
271*cda5da8dSAndroid Build Coastguard Worker# Context types for fixed start method
272*cda5da8dSAndroid Build Coastguard Worker#
273*cda5da8dSAndroid Build Coastguard Worker
274*cda5da8dSAndroid Build Coastguard Workerif sys.platform != 'win32':
275*cda5da8dSAndroid Build Coastguard Worker
276*cda5da8dSAndroid Build Coastguard Worker    class ForkProcess(process.BaseProcess):
277*cda5da8dSAndroid Build Coastguard Worker        _start_method = 'fork'
278*cda5da8dSAndroid Build Coastguard Worker        @staticmethod
279*cda5da8dSAndroid Build Coastguard Worker        def _Popen(process_obj):
280*cda5da8dSAndroid Build Coastguard Worker            from .popen_fork import Popen
281*cda5da8dSAndroid Build Coastguard Worker            return Popen(process_obj)
282*cda5da8dSAndroid Build Coastguard Worker
283*cda5da8dSAndroid Build Coastguard Worker    class SpawnProcess(process.BaseProcess):
284*cda5da8dSAndroid Build Coastguard Worker        _start_method = 'spawn'
285*cda5da8dSAndroid Build Coastguard Worker        @staticmethod
286*cda5da8dSAndroid Build Coastguard Worker        def _Popen(process_obj):
287*cda5da8dSAndroid Build Coastguard Worker            from .popen_spawn_posix import Popen
288*cda5da8dSAndroid Build Coastguard Worker            return Popen(process_obj)
289*cda5da8dSAndroid Build Coastguard Worker
290*cda5da8dSAndroid Build Coastguard Worker        @staticmethod
291*cda5da8dSAndroid Build Coastguard Worker        def _after_fork():
292*cda5da8dSAndroid Build Coastguard Worker            # process is spawned, nothing to do
293*cda5da8dSAndroid Build Coastguard Worker            pass
294*cda5da8dSAndroid Build Coastguard Worker
295*cda5da8dSAndroid Build Coastguard Worker    class ForkServerProcess(process.BaseProcess):
296*cda5da8dSAndroid Build Coastguard Worker        _start_method = 'forkserver'
297*cda5da8dSAndroid Build Coastguard Worker        @staticmethod
298*cda5da8dSAndroid Build Coastguard Worker        def _Popen(process_obj):
299*cda5da8dSAndroid Build Coastguard Worker            from .popen_forkserver import Popen
300*cda5da8dSAndroid Build Coastguard Worker            return Popen(process_obj)
301*cda5da8dSAndroid Build Coastguard Worker
302*cda5da8dSAndroid Build Coastguard Worker    class ForkContext(BaseContext):
303*cda5da8dSAndroid Build Coastguard Worker        _name = 'fork'
304*cda5da8dSAndroid Build Coastguard Worker        Process = ForkProcess
305*cda5da8dSAndroid Build Coastguard Worker
306*cda5da8dSAndroid Build Coastguard Worker    class SpawnContext(BaseContext):
307*cda5da8dSAndroid Build Coastguard Worker        _name = 'spawn'
308*cda5da8dSAndroid Build Coastguard Worker        Process = SpawnProcess
309*cda5da8dSAndroid Build Coastguard Worker
310*cda5da8dSAndroid Build Coastguard Worker    class ForkServerContext(BaseContext):
311*cda5da8dSAndroid Build Coastguard Worker        _name = 'forkserver'
312*cda5da8dSAndroid Build Coastguard Worker        Process = ForkServerProcess
313*cda5da8dSAndroid Build Coastguard Worker        def _check_available(self):
314*cda5da8dSAndroid Build Coastguard Worker            if not reduction.HAVE_SEND_HANDLE:
315*cda5da8dSAndroid Build Coastguard Worker                raise ValueError('forkserver start method not available')
316*cda5da8dSAndroid Build Coastguard Worker
317*cda5da8dSAndroid Build Coastguard Worker    _concrete_contexts = {
318*cda5da8dSAndroid Build Coastguard Worker        'fork': ForkContext(),
319*cda5da8dSAndroid Build Coastguard Worker        'spawn': SpawnContext(),
320*cda5da8dSAndroid Build Coastguard Worker        'forkserver': ForkServerContext(),
321*cda5da8dSAndroid Build Coastguard Worker    }
322*cda5da8dSAndroid Build Coastguard Worker    if sys.platform == 'darwin':
323*cda5da8dSAndroid Build Coastguard Worker        # bpo-33725: running arbitrary code after fork() is no longer reliable
324*cda5da8dSAndroid Build Coastguard Worker        # on macOS since macOS 10.14 (Mojave). Use spawn by default instead.
325*cda5da8dSAndroid Build Coastguard Worker        _default_context = DefaultContext(_concrete_contexts['spawn'])
326*cda5da8dSAndroid Build Coastguard Worker    else:
327*cda5da8dSAndroid Build Coastguard Worker        _default_context = DefaultContext(_concrete_contexts['fork'])
328*cda5da8dSAndroid Build Coastguard Worker
329*cda5da8dSAndroid Build Coastguard Workerelse:
330*cda5da8dSAndroid Build Coastguard Worker
331*cda5da8dSAndroid Build Coastguard Worker    class SpawnProcess(process.BaseProcess):
332*cda5da8dSAndroid Build Coastguard Worker        _start_method = 'spawn'
333*cda5da8dSAndroid Build Coastguard Worker        @staticmethod
334*cda5da8dSAndroid Build Coastguard Worker        def _Popen(process_obj):
335*cda5da8dSAndroid Build Coastguard Worker            from .popen_spawn_win32 import Popen
336*cda5da8dSAndroid Build Coastguard Worker            return Popen(process_obj)
337*cda5da8dSAndroid Build Coastguard Worker
338*cda5da8dSAndroid Build Coastguard Worker        @staticmethod
339*cda5da8dSAndroid Build Coastguard Worker        def _after_fork():
340*cda5da8dSAndroid Build Coastguard Worker            # process is spawned, nothing to do
341*cda5da8dSAndroid Build Coastguard Worker            pass
342*cda5da8dSAndroid Build Coastguard Worker
343*cda5da8dSAndroid Build Coastguard Worker    class SpawnContext(BaseContext):
344*cda5da8dSAndroid Build Coastguard Worker        _name = 'spawn'
345*cda5da8dSAndroid Build Coastguard Worker        Process = SpawnProcess
346*cda5da8dSAndroid Build Coastguard Worker
347*cda5da8dSAndroid Build Coastguard Worker    _concrete_contexts = {
348*cda5da8dSAndroid Build Coastguard Worker        'spawn': SpawnContext(),
349*cda5da8dSAndroid Build Coastguard Worker    }
350*cda5da8dSAndroid Build Coastguard Worker    _default_context = DefaultContext(_concrete_contexts['spawn'])
351*cda5da8dSAndroid Build Coastguard Worker
352*cda5da8dSAndroid Build Coastguard Worker#
353*cda5da8dSAndroid Build Coastguard Worker# Force the start method
354*cda5da8dSAndroid Build Coastguard Worker#
355*cda5da8dSAndroid Build Coastguard Worker
356*cda5da8dSAndroid Build Coastguard Workerdef _force_start_method(method):
357*cda5da8dSAndroid Build Coastguard Worker    _default_context._actual_context = _concrete_contexts[method]
358*cda5da8dSAndroid Build Coastguard Worker
359*cda5da8dSAndroid Build Coastguard Worker#
360*cda5da8dSAndroid Build Coastguard Worker# Check that the current thread is spawning a child process
361*cda5da8dSAndroid Build Coastguard Worker#
362*cda5da8dSAndroid Build Coastguard Worker
363*cda5da8dSAndroid Build Coastguard Worker_tls = threading.local()
364*cda5da8dSAndroid Build Coastguard Worker
365*cda5da8dSAndroid Build Coastguard Workerdef get_spawning_popen():
366*cda5da8dSAndroid Build Coastguard Worker    return getattr(_tls, 'spawning_popen', None)
367*cda5da8dSAndroid Build Coastguard Worker
368*cda5da8dSAndroid Build Coastguard Workerdef set_spawning_popen(popen):
369*cda5da8dSAndroid Build Coastguard Worker    _tls.spawning_popen = popen
370*cda5da8dSAndroid Build Coastguard Worker
371*cda5da8dSAndroid Build Coastguard Workerdef assert_spawning(obj):
372*cda5da8dSAndroid Build Coastguard Worker    if get_spawning_popen() is None:
373*cda5da8dSAndroid Build Coastguard Worker        raise RuntimeError(
374*cda5da8dSAndroid Build Coastguard Worker            '%s objects should only be shared between processes'
375*cda5da8dSAndroid Build Coastguard Worker            ' through inheritance' % type(obj).__name__
376*cda5da8dSAndroid Build Coastguard Worker            )
377