1919from .import process
2020
2121__all__ = [
22- 'sub_debug' ,'debug' ,'info' ,'sub_warning' ,'get_logger' ,
22+ 'sub_debug' ,'debug' ,'info' ,'sub_warning' ,'warn' , ' get_logger' ,
2323'log_to_stderr' ,'get_temp_dir' ,'register_after_fork' ,
2424'is_exiting' ,'Finalize' ,'ForkAwareThreadLock' ,'ForkAwareLocal' ,
2525'close_all_fds_except' ,'SUBDEBUG' ,'SUBWARNING' ,
3434DEBUG = 10
3535INFO = 20
3636SUBWARNING = 25
37+ WARNING = 30
3738
3839LOGGER_NAME = 'multiprocessing'
3940DEFAULT_LOGGING_FORMAT = '[%(levelname)s/%(processName)s] %(message)s'
@@ -53,6 +54,10 @@ def info(msg, *args):
5354if _logger :
5455_logger .log (INFO ,msg ,* args ,stacklevel = 2 )
5556
57+ def warn (msg ,* args ):
58+ if _logger :
59+ _logger .log (WARNING ,msg ,* args ,stacklevel = 2 )
60+
5661def sub_warning (msg ,* args ):
5762if _logger :
5863_logger .log (SUBWARNING ,msg ,* args ,stacklevel = 2 )
@@ -121,6 +126,21 @@ def is_abstract_socket_namespace(address):
121126# Function returning a temp directory which will be removed on exit
122127#
123128
129+ # Maximum length of a socket file path is usually between 92 and 108 [1],
130+ # but Linux is known to use a size of 108 [2]. BSD-based systems usually
131+ # use a size of 104 or 108 and Windows does not create AF_UNIX sockets.
132+ #
133+ # [1]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_un.h.html
134+ # [2]: https://man7.org/linux/man-pages/man7/unix.7.html.
135+
136+ if sys .platform == 'linux' :
137+ _SUN_PATH_MAX = 108
138+ elif sys .platform .startswith (('openbsd' ,'freebsd' )):
139+ _SUN_PATH_MAX = 104
140+ else :
141+ # On Windows platforms, we do not create AF_UNIX sockets.
142+ _SUN_PATH_MAX = None if os .name == 'nt' else 92
143+
124144def _remove_temp_dir (rmtree ,tempdir ):
125145rmtree (tempdir )
126146
@@ -130,12 +150,67 @@ def _remove_temp_dir(rmtree, tempdir):
130150if current_process is not None :
131151current_process ._config ['tempdir' ]= None
132152
153+ def _get_base_temp_dir (tempfile ):
154+ """Get a temporary directory where socket files will be created.
155+
156+ To prevent additional imports, pass a pre-imported 'tempfile' module.
157+ """
158+ if os .name == 'nt' :
159+ return None
160+ # Most of the time, the default temporary directory is /tmp. Thus,
161+ # listener sockets files "$TMPDIR/pymp-XXXXXXXX/sock-XXXXXXXX" do
162+ # not have a path length exceeding SUN_PATH_MAX.
163+ #
164+ # If users specify their own temporary directory, we may be unable
165+ # to create those files. Therefore, we fall back to the system-wide
166+ # temporary directory /tmp, assumed to exist on POSIX systems.
167+ #
168+ # See https://github.com/python/cpython/issues/132124.
169+ base_tempdir = tempfile .gettempdir ()
170+ # Files created in a temporary directory are suffixed by a string
171+ # generated by tempfile._RandomNameSequence, which, by design,
172+ # is 8 characters long.
173+ #
174+ # Thus, the length of socket filename will be:
175+ #
176+ # len(base_tempdir + '/pymp-XXXXXXXX' + '/sock-XXXXXXXX')
177+ sun_path_len = len (base_tempdir )+ 14 + 14
178+ if sun_path_len <= _SUN_PATH_MAX :
179+ return base_tempdir
180+ # Fallback to the default system-wide temporary directory.
181+ # This ignores user-defined environment variables.
182+ #
183+ # On POSIX systems, /tmp MUST be writable by any application [1].
184+ # We however emit a warning if this is not the case to prevent
185+ # obscure errors later in the execution.
186+ #
187+ # On some legacy systems, /var/tmp and /usr/tmp can be present
188+ # and will be used instead.
189+ #
190+ # [1]: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s18.html
191+ dirlist = ['/tmp' ,'/var/tmp' ,'/usr/tmp' ]
192+ try :
193+ base_system_tempdir = tempfile ._get_default_tempdir (dirlist )
194+ except FileNotFoundError :
195+ warn ("Process-wide temporary directory %s will not be usable for "
196+ "creating socket files and no usable system-wide temporary "
197+ "directory was found in %s" ,base_tempdir ,dirlist )
198+ # At this point, the system-wide temporary directory is not usable
199+ # but we may assume that the user-defined one is, even if we will
200+ # not be able to write socket files out there.
201+ return base_tempdir
202+ warn ("Ignoring user-defined temporary directory: %s" ,base_tempdir )
203+ # at most max(map(len, dirlist)) + 14 + 14 = 36 characters
204+ assert len (base_system_tempdir )+ 14 + 14 <= _SUN_PATH_MAX
205+ return base_system_tempdir
206+
133207def get_temp_dir ():
134208# get name of a temp directory which will be automatically cleaned up
135209tempdir = process .current_process ()._config .get ('tempdir' )
136210if tempdir is None :
137211import shutil ,tempfile
138- tempdir = tempfile .mkdtemp (prefix = 'pymp-' )
212+ base_tempdir = _get_base_temp_dir (tempfile )
213+ tempdir = tempfile .mkdtemp (prefix = 'pymp-' ,dir = base_tempdir )
139214info ('created temp directory %s' ,tempdir )
140215# keep a strong reference to shutil.rmtree(), since the finalizer
141216# can be called late during Python shutdown