1# Copyright 2020, 2021 PaGMO development team 2# 3# This file is part of the pygmo library. 4# 5# This Source Code Form is subject to the terms of the Mozilla 6# Public License v. 2.0. If a copy of the MPL was not distributed 7# with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 9 10def _get_spawn_context(): 11 # Small utlity to get a context that will use the 'spawn' method to 12 # create new processes with the multiprocessing module. We want to enforce 13 # a uniform way of creating new processes across platforms in 14 # order to prevent users from implicitly relying on platform-specific 15 # behaviour (e.g., fork()), only to discover later that their 16 # code is not portable across platforms. See: 17 # https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods 18 19 import multiprocessing as mp 20 21 return mp.get_context('spawn') 22 23 24class _temp_disable_sigint(object): 25 # A small helper context class to disable CTRL+C temporarily. 26 27 def __enter__(self): 28 import signal 29 # Store the previous sigint handler and assign the new sig handler 30 # (i.e., ignore SIGINT). 31 self._prev_signal = signal.signal(signal.SIGINT, signal.SIG_IGN) 32 33 def __exit__(self, type, value, traceback): 34 import signal 35 # Restore the previous sighandler. 36 signal.signal(signal.SIGINT, self._prev_signal) 37 38 39def _make_pool(processes): 40 # A small factory function to create a process pool. 41 # It accomplishes the tasks of selecting the correct method for 42 # starting the processes ("spawn") and making sure that the 43 # created processes will ignore the SIGINT signal (this prevents 44 # troubles when the user issues an interruption with ctrl+c from 45 # the main process). 46 47 if processes is not None and not isinstance(processes, int): 48 raise TypeError("The 'processes' argument must be None or an int") 49 50 if processes is not None and processes <= 0: 51 raise ValueError( 52 "The 'processes' argument, if not None, must be strictly positive") 53 54 # Get the context for spawning the process. 55 mp_ctx = _get_spawn_context() 56 57 # NOTE: we temporarily disable sigint while creating the pool. 58 # This ensures that the processes created in the pool will ignore 59 # interruptions issued via ctrl+c (only the main process will 60 # be affected by them). 61 with _temp_disable_sigint(): 62 pool = mp_ctx.Pool(processes=processes) 63 64 pool_size = mp_ctx.cpu_count() if processes is None else processes 65 66 # Return the created pool and its size. 67 return pool, pool_size 68