17db96d56Sopenharmony_ci# 27db96d56Sopenharmony_ci# Module providing various facilities to other parts of the package 37db96d56Sopenharmony_ci# 47db96d56Sopenharmony_ci# multiprocessing/util.py 57db96d56Sopenharmony_ci# 67db96d56Sopenharmony_ci# Copyright (c) 2006-2008, R Oudkerk 77db96d56Sopenharmony_ci# Licensed to PSF under a Contributor Agreement. 87db96d56Sopenharmony_ci# 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ciimport os 117db96d56Sopenharmony_ciimport itertools 127db96d56Sopenharmony_ciimport sys 137db96d56Sopenharmony_ciimport weakref 147db96d56Sopenharmony_ciimport atexit 157db96d56Sopenharmony_ciimport threading # we want threading to install it's 167db96d56Sopenharmony_ci # cleanup function before multiprocessing does 177db96d56Sopenharmony_cifrom subprocess import _args_from_interpreter_flags 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_cifrom . import process 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci__all__ = [ 227db96d56Sopenharmony_ci 'sub_debug', 'debug', 'info', 'sub_warning', 'get_logger', 237db96d56Sopenharmony_ci 'log_to_stderr', 'get_temp_dir', 'register_after_fork', 247db96d56Sopenharmony_ci 'is_exiting', 'Finalize', 'ForkAwareThreadLock', 'ForkAwareLocal', 257db96d56Sopenharmony_ci 'close_all_fds_except', 'SUBDEBUG', 'SUBWARNING', 267db96d56Sopenharmony_ci ] 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_ci# 297db96d56Sopenharmony_ci# Logging 307db96d56Sopenharmony_ci# 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ciNOTSET = 0 337db96d56Sopenharmony_ciSUBDEBUG = 5 347db96d56Sopenharmony_ciDEBUG = 10 357db96d56Sopenharmony_ciINFO = 20 367db96d56Sopenharmony_ciSUBWARNING = 25 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ciLOGGER_NAME = 'multiprocessing' 397db96d56Sopenharmony_ciDEFAULT_LOGGING_FORMAT = '[%(levelname)s/%(processName)s] %(message)s' 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci_logger = None 427db96d56Sopenharmony_ci_log_to_stderr = False 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_cidef sub_debug(msg, *args): 457db96d56Sopenharmony_ci if _logger: 467db96d56Sopenharmony_ci _logger.log(SUBDEBUG, msg, *args) 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_cidef debug(msg, *args): 497db96d56Sopenharmony_ci if _logger: 507db96d56Sopenharmony_ci _logger.log(DEBUG, msg, *args) 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_cidef info(msg, *args): 537db96d56Sopenharmony_ci if _logger: 547db96d56Sopenharmony_ci _logger.log(INFO, msg, *args) 557db96d56Sopenharmony_ci 567db96d56Sopenharmony_cidef sub_warning(msg, *args): 577db96d56Sopenharmony_ci if _logger: 587db96d56Sopenharmony_ci _logger.log(SUBWARNING, msg, *args) 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_cidef get_logger(): 617db96d56Sopenharmony_ci ''' 627db96d56Sopenharmony_ci Returns logger used by multiprocessing 637db96d56Sopenharmony_ci ''' 647db96d56Sopenharmony_ci global _logger 657db96d56Sopenharmony_ci import logging 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci logging._acquireLock() 687db96d56Sopenharmony_ci try: 697db96d56Sopenharmony_ci if not _logger: 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci _logger = logging.getLogger(LOGGER_NAME) 727db96d56Sopenharmony_ci _logger.propagate = 0 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci # XXX multiprocessing should cleanup before logging 757db96d56Sopenharmony_ci if hasattr(atexit, 'unregister'): 767db96d56Sopenharmony_ci atexit.unregister(_exit_function) 777db96d56Sopenharmony_ci atexit.register(_exit_function) 787db96d56Sopenharmony_ci else: 797db96d56Sopenharmony_ci atexit._exithandlers.remove((_exit_function, (), {})) 807db96d56Sopenharmony_ci atexit._exithandlers.append((_exit_function, (), {})) 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_ci finally: 837db96d56Sopenharmony_ci logging._releaseLock() 847db96d56Sopenharmony_ci 857db96d56Sopenharmony_ci return _logger 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_cidef log_to_stderr(level=None): 887db96d56Sopenharmony_ci ''' 897db96d56Sopenharmony_ci Turn on logging and add a handler which prints to stderr 907db96d56Sopenharmony_ci ''' 917db96d56Sopenharmony_ci global _log_to_stderr 927db96d56Sopenharmony_ci import logging 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ci logger = get_logger() 957db96d56Sopenharmony_ci formatter = logging.Formatter(DEFAULT_LOGGING_FORMAT) 967db96d56Sopenharmony_ci handler = logging.StreamHandler() 977db96d56Sopenharmony_ci handler.setFormatter(formatter) 987db96d56Sopenharmony_ci logger.addHandler(handler) 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci if level: 1017db96d56Sopenharmony_ci logger.setLevel(level) 1027db96d56Sopenharmony_ci _log_to_stderr = True 1037db96d56Sopenharmony_ci return _logger 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci# Abstract socket support 1077db96d56Sopenharmony_ci 1087db96d56Sopenharmony_cidef _platform_supports_abstract_sockets(): 1097db96d56Sopenharmony_ci if sys.platform == "linux": 1107db96d56Sopenharmony_ci return True 1117db96d56Sopenharmony_ci if hasattr(sys, 'getandroidapilevel'): 1127db96d56Sopenharmony_ci return True 1137db96d56Sopenharmony_ci return False 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci 1167db96d56Sopenharmony_cidef is_abstract_socket_namespace(address): 1177db96d56Sopenharmony_ci if not address: 1187db96d56Sopenharmony_ci return False 1197db96d56Sopenharmony_ci if isinstance(address, bytes): 1207db96d56Sopenharmony_ci return address[0] == 0 1217db96d56Sopenharmony_ci elif isinstance(address, str): 1227db96d56Sopenharmony_ci return address[0] == "\0" 1237db96d56Sopenharmony_ci raise TypeError(f'address type of {address!r} unrecognized') 1247db96d56Sopenharmony_ci 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_ciabstract_sockets_supported = _platform_supports_abstract_sockets() 1277db96d56Sopenharmony_ci 1287db96d56Sopenharmony_ci# 1297db96d56Sopenharmony_ci# Function returning a temp directory which will be removed on exit 1307db96d56Sopenharmony_ci# 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_cidef _remove_temp_dir(rmtree, tempdir): 1337db96d56Sopenharmony_ci rmtree(tempdir) 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci current_process = process.current_process() 1367db96d56Sopenharmony_ci # current_process() can be None if the finalizer is called 1377db96d56Sopenharmony_ci # late during Python finalization 1387db96d56Sopenharmony_ci if current_process is not None: 1397db96d56Sopenharmony_ci current_process._config['tempdir'] = None 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_cidef get_temp_dir(): 1427db96d56Sopenharmony_ci # get name of a temp directory which will be automatically cleaned up 1437db96d56Sopenharmony_ci tempdir = process.current_process()._config.get('tempdir') 1447db96d56Sopenharmony_ci if tempdir is None: 1457db96d56Sopenharmony_ci import shutil, tempfile 1467db96d56Sopenharmony_ci tempdir = tempfile.mkdtemp(prefix='pymp-') 1477db96d56Sopenharmony_ci info('created temp directory %s', tempdir) 1487db96d56Sopenharmony_ci # keep a strong reference to shutil.rmtree(), since the finalizer 1497db96d56Sopenharmony_ci # can be called late during Python shutdown 1507db96d56Sopenharmony_ci Finalize(None, _remove_temp_dir, args=(shutil.rmtree, tempdir), 1517db96d56Sopenharmony_ci exitpriority=-100) 1527db96d56Sopenharmony_ci process.current_process()._config['tempdir'] = tempdir 1537db96d56Sopenharmony_ci return tempdir 1547db96d56Sopenharmony_ci 1557db96d56Sopenharmony_ci# 1567db96d56Sopenharmony_ci# Support for reinitialization of objects when bootstrapping a child process 1577db96d56Sopenharmony_ci# 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci_afterfork_registry = weakref.WeakValueDictionary() 1607db96d56Sopenharmony_ci_afterfork_counter = itertools.count() 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_cidef _run_after_forkers(): 1637db96d56Sopenharmony_ci items = list(_afterfork_registry.items()) 1647db96d56Sopenharmony_ci items.sort() 1657db96d56Sopenharmony_ci for (index, ident, func), obj in items: 1667db96d56Sopenharmony_ci try: 1677db96d56Sopenharmony_ci func(obj) 1687db96d56Sopenharmony_ci except Exception as e: 1697db96d56Sopenharmony_ci info('after forker raised exception %s', e) 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_cidef register_after_fork(obj, func): 1727db96d56Sopenharmony_ci _afterfork_registry[(next(_afterfork_counter), id(obj), func)] = obj 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci# 1757db96d56Sopenharmony_ci# Finalization using weakrefs 1767db96d56Sopenharmony_ci# 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_ci_finalizer_registry = {} 1797db96d56Sopenharmony_ci_finalizer_counter = itertools.count() 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ciclass Finalize(object): 1837db96d56Sopenharmony_ci ''' 1847db96d56Sopenharmony_ci Class which supports object finalization using weakrefs 1857db96d56Sopenharmony_ci ''' 1867db96d56Sopenharmony_ci def __init__(self, obj, callback, args=(), kwargs=None, exitpriority=None): 1877db96d56Sopenharmony_ci if (exitpriority is not None) and not isinstance(exitpriority,int): 1887db96d56Sopenharmony_ci raise TypeError( 1897db96d56Sopenharmony_ci "Exitpriority ({0!r}) must be None or int, not {1!s}".format( 1907db96d56Sopenharmony_ci exitpriority, type(exitpriority))) 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_ci if obj is not None: 1937db96d56Sopenharmony_ci self._weakref = weakref.ref(obj, self) 1947db96d56Sopenharmony_ci elif exitpriority is None: 1957db96d56Sopenharmony_ci raise ValueError("Without object, exitpriority cannot be None") 1967db96d56Sopenharmony_ci 1977db96d56Sopenharmony_ci self._callback = callback 1987db96d56Sopenharmony_ci self._args = args 1997db96d56Sopenharmony_ci self._kwargs = kwargs or {} 2007db96d56Sopenharmony_ci self._key = (exitpriority, next(_finalizer_counter)) 2017db96d56Sopenharmony_ci self._pid = os.getpid() 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci _finalizer_registry[self._key] = self 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci def __call__(self, wr=None, 2067db96d56Sopenharmony_ci # Need to bind these locally because the globals can have 2077db96d56Sopenharmony_ci # been cleared at shutdown 2087db96d56Sopenharmony_ci _finalizer_registry=_finalizer_registry, 2097db96d56Sopenharmony_ci sub_debug=sub_debug, getpid=os.getpid): 2107db96d56Sopenharmony_ci ''' 2117db96d56Sopenharmony_ci Run the callback unless it has already been called or cancelled 2127db96d56Sopenharmony_ci ''' 2137db96d56Sopenharmony_ci try: 2147db96d56Sopenharmony_ci del _finalizer_registry[self._key] 2157db96d56Sopenharmony_ci except KeyError: 2167db96d56Sopenharmony_ci sub_debug('finalizer no longer registered') 2177db96d56Sopenharmony_ci else: 2187db96d56Sopenharmony_ci if self._pid != getpid(): 2197db96d56Sopenharmony_ci sub_debug('finalizer ignored because different process') 2207db96d56Sopenharmony_ci res = None 2217db96d56Sopenharmony_ci else: 2227db96d56Sopenharmony_ci sub_debug('finalizer calling %s with args %s and kwargs %s', 2237db96d56Sopenharmony_ci self._callback, self._args, self._kwargs) 2247db96d56Sopenharmony_ci res = self._callback(*self._args, **self._kwargs) 2257db96d56Sopenharmony_ci self._weakref = self._callback = self._args = \ 2267db96d56Sopenharmony_ci self._kwargs = self._key = None 2277db96d56Sopenharmony_ci return res 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci def cancel(self): 2307db96d56Sopenharmony_ci ''' 2317db96d56Sopenharmony_ci Cancel finalization of the object 2327db96d56Sopenharmony_ci ''' 2337db96d56Sopenharmony_ci try: 2347db96d56Sopenharmony_ci del _finalizer_registry[self._key] 2357db96d56Sopenharmony_ci except KeyError: 2367db96d56Sopenharmony_ci pass 2377db96d56Sopenharmony_ci else: 2387db96d56Sopenharmony_ci self._weakref = self._callback = self._args = \ 2397db96d56Sopenharmony_ci self._kwargs = self._key = None 2407db96d56Sopenharmony_ci 2417db96d56Sopenharmony_ci def still_active(self): 2427db96d56Sopenharmony_ci ''' 2437db96d56Sopenharmony_ci Return whether this finalizer is still waiting to invoke callback 2447db96d56Sopenharmony_ci ''' 2457db96d56Sopenharmony_ci return self._key in _finalizer_registry 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ci def __repr__(self): 2487db96d56Sopenharmony_ci try: 2497db96d56Sopenharmony_ci obj = self._weakref() 2507db96d56Sopenharmony_ci except (AttributeError, TypeError): 2517db96d56Sopenharmony_ci obj = None 2527db96d56Sopenharmony_ci 2537db96d56Sopenharmony_ci if obj is None: 2547db96d56Sopenharmony_ci return '<%s object, dead>' % self.__class__.__name__ 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_ci x = '<%s object, callback=%s' % ( 2577db96d56Sopenharmony_ci self.__class__.__name__, 2587db96d56Sopenharmony_ci getattr(self._callback, '__name__', self._callback)) 2597db96d56Sopenharmony_ci if self._args: 2607db96d56Sopenharmony_ci x += ', args=' + str(self._args) 2617db96d56Sopenharmony_ci if self._kwargs: 2627db96d56Sopenharmony_ci x += ', kwargs=' + str(self._kwargs) 2637db96d56Sopenharmony_ci if self._key[0] is not None: 2647db96d56Sopenharmony_ci x += ', exitpriority=' + str(self._key[0]) 2657db96d56Sopenharmony_ci return x + '>' 2667db96d56Sopenharmony_ci 2677db96d56Sopenharmony_ci 2687db96d56Sopenharmony_cidef _run_finalizers(minpriority=None): 2697db96d56Sopenharmony_ci ''' 2707db96d56Sopenharmony_ci Run all finalizers whose exit priority is not None and at least minpriority 2717db96d56Sopenharmony_ci 2727db96d56Sopenharmony_ci Finalizers with highest priority are called first; finalizers with 2737db96d56Sopenharmony_ci the same priority will be called in reverse order of creation. 2747db96d56Sopenharmony_ci ''' 2757db96d56Sopenharmony_ci if _finalizer_registry is None: 2767db96d56Sopenharmony_ci # This function may be called after this module's globals are 2777db96d56Sopenharmony_ci # destroyed. See the _exit_function function in this module for more 2787db96d56Sopenharmony_ci # notes. 2797db96d56Sopenharmony_ci return 2807db96d56Sopenharmony_ci 2817db96d56Sopenharmony_ci if minpriority is None: 2827db96d56Sopenharmony_ci f = lambda p : p[0] is not None 2837db96d56Sopenharmony_ci else: 2847db96d56Sopenharmony_ci f = lambda p : p[0] is not None and p[0] >= minpriority 2857db96d56Sopenharmony_ci 2867db96d56Sopenharmony_ci # Careful: _finalizer_registry may be mutated while this function 2877db96d56Sopenharmony_ci # is running (either by a GC run or by another thread). 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_ci # list(_finalizer_registry) should be atomic, while 2907db96d56Sopenharmony_ci # list(_finalizer_registry.items()) is not. 2917db96d56Sopenharmony_ci keys = [key for key in list(_finalizer_registry) if f(key)] 2927db96d56Sopenharmony_ci keys.sort(reverse=True) 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ci for key in keys: 2957db96d56Sopenharmony_ci finalizer = _finalizer_registry.get(key) 2967db96d56Sopenharmony_ci # key may have been removed from the registry 2977db96d56Sopenharmony_ci if finalizer is not None: 2987db96d56Sopenharmony_ci sub_debug('calling %s', finalizer) 2997db96d56Sopenharmony_ci try: 3007db96d56Sopenharmony_ci finalizer() 3017db96d56Sopenharmony_ci except Exception: 3027db96d56Sopenharmony_ci import traceback 3037db96d56Sopenharmony_ci traceback.print_exc() 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ci if minpriority is None: 3067db96d56Sopenharmony_ci _finalizer_registry.clear() 3077db96d56Sopenharmony_ci 3087db96d56Sopenharmony_ci# 3097db96d56Sopenharmony_ci# Clean up on exit 3107db96d56Sopenharmony_ci# 3117db96d56Sopenharmony_ci 3127db96d56Sopenharmony_cidef is_exiting(): 3137db96d56Sopenharmony_ci ''' 3147db96d56Sopenharmony_ci Returns true if the process is shutting down 3157db96d56Sopenharmony_ci ''' 3167db96d56Sopenharmony_ci return _exiting or _exiting is None 3177db96d56Sopenharmony_ci 3187db96d56Sopenharmony_ci_exiting = False 3197db96d56Sopenharmony_ci 3207db96d56Sopenharmony_cidef _exit_function(info=info, debug=debug, _run_finalizers=_run_finalizers, 3217db96d56Sopenharmony_ci active_children=process.active_children, 3227db96d56Sopenharmony_ci current_process=process.current_process): 3237db96d56Sopenharmony_ci # We hold on to references to functions in the arglist due to the 3247db96d56Sopenharmony_ci # situation described below, where this function is called after this 3257db96d56Sopenharmony_ci # module's globals are destroyed. 3267db96d56Sopenharmony_ci 3277db96d56Sopenharmony_ci global _exiting 3287db96d56Sopenharmony_ci 3297db96d56Sopenharmony_ci if not _exiting: 3307db96d56Sopenharmony_ci _exiting = True 3317db96d56Sopenharmony_ci 3327db96d56Sopenharmony_ci info('process shutting down') 3337db96d56Sopenharmony_ci debug('running all "atexit" finalizers with priority >= 0') 3347db96d56Sopenharmony_ci _run_finalizers(0) 3357db96d56Sopenharmony_ci 3367db96d56Sopenharmony_ci if current_process() is not None: 3377db96d56Sopenharmony_ci # We check if the current process is None here because if 3387db96d56Sopenharmony_ci # it's None, any call to ``active_children()`` will raise 3397db96d56Sopenharmony_ci # an AttributeError (active_children winds up trying to 3407db96d56Sopenharmony_ci # get attributes from util._current_process). One 3417db96d56Sopenharmony_ci # situation where this can happen is if someone has 3427db96d56Sopenharmony_ci # manipulated sys.modules, causing this module to be 3437db96d56Sopenharmony_ci # garbage collected. The destructor for the module type 3447db96d56Sopenharmony_ci # then replaces all values in the module dict with None. 3457db96d56Sopenharmony_ci # For instance, after setuptools runs a test it replaces 3467db96d56Sopenharmony_ci # sys.modules with a copy created earlier. See issues 3477db96d56Sopenharmony_ci # #9775 and #15881. Also related: #4106, #9205, and 3487db96d56Sopenharmony_ci # #9207. 3497db96d56Sopenharmony_ci 3507db96d56Sopenharmony_ci for p in active_children(): 3517db96d56Sopenharmony_ci if p.daemon: 3527db96d56Sopenharmony_ci info('calling terminate() for daemon %s', p.name) 3537db96d56Sopenharmony_ci p._popen.terminate() 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ci for p in active_children(): 3567db96d56Sopenharmony_ci info('calling join() for process %s', p.name) 3577db96d56Sopenharmony_ci p.join() 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci debug('running the remaining "atexit" finalizers') 3607db96d56Sopenharmony_ci _run_finalizers() 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_ciatexit.register(_exit_function) 3637db96d56Sopenharmony_ci 3647db96d56Sopenharmony_ci# 3657db96d56Sopenharmony_ci# Some fork aware types 3667db96d56Sopenharmony_ci# 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ciclass ForkAwareThreadLock(object): 3697db96d56Sopenharmony_ci def __init__(self): 3707db96d56Sopenharmony_ci self._lock = threading.Lock() 3717db96d56Sopenharmony_ci self.acquire = self._lock.acquire 3727db96d56Sopenharmony_ci self.release = self._lock.release 3737db96d56Sopenharmony_ci register_after_fork(self, ForkAwareThreadLock._at_fork_reinit) 3747db96d56Sopenharmony_ci 3757db96d56Sopenharmony_ci def _at_fork_reinit(self): 3767db96d56Sopenharmony_ci self._lock._at_fork_reinit() 3777db96d56Sopenharmony_ci 3787db96d56Sopenharmony_ci def __enter__(self): 3797db96d56Sopenharmony_ci return self._lock.__enter__() 3807db96d56Sopenharmony_ci 3817db96d56Sopenharmony_ci def __exit__(self, *args): 3827db96d56Sopenharmony_ci return self._lock.__exit__(*args) 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci 3857db96d56Sopenharmony_ciclass ForkAwareLocal(threading.local): 3867db96d56Sopenharmony_ci def __init__(self): 3877db96d56Sopenharmony_ci register_after_fork(self, lambda obj : obj.__dict__.clear()) 3887db96d56Sopenharmony_ci def __reduce__(self): 3897db96d56Sopenharmony_ci return type(self), () 3907db96d56Sopenharmony_ci 3917db96d56Sopenharmony_ci# 3927db96d56Sopenharmony_ci# Close fds except those specified 3937db96d56Sopenharmony_ci# 3947db96d56Sopenharmony_ci 3957db96d56Sopenharmony_citry: 3967db96d56Sopenharmony_ci MAXFD = os.sysconf("SC_OPEN_MAX") 3977db96d56Sopenharmony_ciexcept Exception: 3987db96d56Sopenharmony_ci MAXFD = 256 3997db96d56Sopenharmony_ci 4007db96d56Sopenharmony_cidef close_all_fds_except(fds): 4017db96d56Sopenharmony_ci fds = list(fds) + [-1, MAXFD] 4027db96d56Sopenharmony_ci fds.sort() 4037db96d56Sopenharmony_ci assert fds[-1] == MAXFD, 'fd too large' 4047db96d56Sopenharmony_ci for i in range(len(fds) - 1): 4057db96d56Sopenharmony_ci os.closerange(fds[i]+1, fds[i+1]) 4067db96d56Sopenharmony_ci# 4077db96d56Sopenharmony_ci# Close sys.stdin and replace stdin with os.devnull 4087db96d56Sopenharmony_ci# 4097db96d56Sopenharmony_ci 4107db96d56Sopenharmony_cidef _close_stdin(): 4117db96d56Sopenharmony_ci if sys.stdin is None: 4127db96d56Sopenharmony_ci return 4137db96d56Sopenharmony_ci 4147db96d56Sopenharmony_ci try: 4157db96d56Sopenharmony_ci sys.stdin.close() 4167db96d56Sopenharmony_ci except (OSError, ValueError): 4177db96d56Sopenharmony_ci pass 4187db96d56Sopenharmony_ci 4197db96d56Sopenharmony_ci try: 4207db96d56Sopenharmony_ci fd = os.open(os.devnull, os.O_RDONLY) 4217db96d56Sopenharmony_ci try: 4227db96d56Sopenharmony_ci sys.stdin = open(fd, encoding="utf-8", closefd=False) 4237db96d56Sopenharmony_ci except: 4247db96d56Sopenharmony_ci os.close(fd) 4257db96d56Sopenharmony_ci raise 4267db96d56Sopenharmony_ci except (OSError, ValueError): 4277db96d56Sopenharmony_ci pass 4287db96d56Sopenharmony_ci 4297db96d56Sopenharmony_ci# 4307db96d56Sopenharmony_ci# Flush standard streams, if any 4317db96d56Sopenharmony_ci# 4327db96d56Sopenharmony_ci 4337db96d56Sopenharmony_cidef _flush_std_streams(): 4347db96d56Sopenharmony_ci try: 4357db96d56Sopenharmony_ci sys.stdout.flush() 4367db96d56Sopenharmony_ci except (AttributeError, ValueError): 4377db96d56Sopenharmony_ci pass 4387db96d56Sopenharmony_ci try: 4397db96d56Sopenharmony_ci sys.stderr.flush() 4407db96d56Sopenharmony_ci except (AttributeError, ValueError): 4417db96d56Sopenharmony_ci pass 4427db96d56Sopenharmony_ci 4437db96d56Sopenharmony_ci# 4447db96d56Sopenharmony_ci# Start a program with only specified fds kept open 4457db96d56Sopenharmony_ci# 4467db96d56Sopenharmony_ci 4477db96d56Sopenharmony_cidef spawnv_passfds(path, args, passfds): 4487db96d56Sopenharmony_ci import _posixsubprocess 4497db96d56Sopenharmony_ci import subprocess 4507db96d56Sopenharmony_ci passfds = tuple(sorted(map(int, passfds))) 4517db96d56Sopenharmony_ci errpipe_read, errpipe_write = os.pipe() 4527db96d56Sopenharmony_ci try: 4537db96d56Sopenharmony_ci return _posixsubprocess.fork_exec( 4547db96d56Sopenharmony_ci args, [path], True, passfds, None, None, 4557db96d56Sopenharmony_ci -1, -1, -1, -1, -1, -1, errpipe_read, errpipe_write, 4567db96d56Sopenharmony_ci False, False, -1, None, None, None, -1, None, 4577db96d56Sopenharmony_ci subprocess._USE_VFORK) 4587db96d56Sopenharmony_ci finally: 4597db96d56Sopenharmony_ci os.close(errpipe_read) 4607db96d56Sopenharmony_ci os.close(errpipe_write) 4617db96d56Sopenharmony_ci 4627db96d56Sopenharmony_ci 4637db96d56Sopenharmony_cidef close_fds(*fds): 4647db96d56Sopenharmony_ci """Close each file descriptor given as an argument""" 4657db96d56Sopenharmony_ci for fd in fds: 4667db96d56Sopenharmony_ci os.close(fd) 4677db96d56Sopenharmony_ci 4687db96d56Sopenharmony_ci 4697db96d56Sopenharmony_cidef _cleanup_tests(): 4707db96d56Sopenharmony_ci """Cleanup multiprocessing resources when multiprocessing tests 4717db96d56Sopenharmony_ci completed.""" 4727db96d56Sopenharmony_ci 4737db96d56Sopenharmony_ci from test import support 4747db96d56Sopenharmony_ci 4757db96d56Sopenharmony_ci # cleanup multiprocessing 4767db96d56Sopenharmony_ci process._cleanup() 4777db96d56Sopenharmony_ci 4787db96d56Sopenharmony_ci # Stop the ForkServer process if it's running 4797db96d56Sopenharmony_ci from multiprocessing import forkserver 4807db96d56Sopenharmony_ci forkserver._forkserver._stop() 4817db96d56Sopenharmony_ci 4827db96d56Sopenharmony_ci # Stop the ResourceTracker process if it's running 4837db96d56Sopenharmony_ci from multiprocessing import resource_tracker 4847db96d56Sopenharmony_ci resource_tracker._resource_tracker._stop() 4857db96d56Sopenharmony_ci 4867db96d56Sopenharmony_ci # bpo-37421: Explicitly call _run_finalizers() to remove immediately 4877db96d56Sopenharmony_ci # temporary directories created by multiprocessing.util.get_temp_dir(). 4887db96d56Sopenharmony_ci _run_finalizers() 4897db96d56Sopenharmony_ci support.gc_collect() 4907db96d56Sopenharmony_ci 4917db96d56Sopenharmony_ci support.reap_children() 492