@@ -34,6 +34,7 @@
3434DEBUG=10
3535INFO=20
3636SUBWARNING=25
37+WARNING=30
37383839LOGGER_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)
555657+def_warn(msg, *args):
58+if_logger:
59+_logger.log(WARNING, msg, *args, stacklevel=2)
60+5661defsub_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#
123128129+# 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+ifsys.platform=='linux':
137+_SUN_PATH_MAX=108
138+elifsys.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=Noneifos.name=='nt'else92
143+124144def_remove_temp_dir(rmtree, tempdir):
125145rmtree(tempdir)
126146@@ -130,12 +150,67 @@ def _remove_temp_dir(rmtree, tempdir):
130150ifcurrent_processisnotNone:
131151current_process._config['tempdir'] =None
132152153+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+ifos.name=='nt':
159+returnNone
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+ifsun_path_len<=_SUN_PATH_MAX:
179+returnbase_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+exceptFileNotFoundError:
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+returnbase_tempdir
202+_warn("Ignoring user-defined temporary directory: %s", base_tempdir)
203+# at most max(map(len, dirlist)) + 14 + 14 = 36 characters
204+assertlen(base_system_tempdir) +14+14<=_SUN_PATH_MAX
205+returnbase_system_tempdir
206+133207defget_temp_dir():
134208# get name of a temp directory which will be automatically cleaned up
135209tempdir=process.current_process()._config.get('tempdir')
136210iftempdirisNone:
137211importshutil, 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