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):
5354    if  _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 ):
5762    if  _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 ):
125145    rmtree (tempdir )
126146
@@ -130,12 +150,67 @@ def _remove_temp_dir(rmtree, tempdir):
130150    if  current_process  is  not None :
131151        current_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 
135209    tempdir  =  process .current_process ()._config .get ('tempdir' )
136210    if  tempdir  is  None :
137211        import  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 )
139214        info ('created temp directory %s' , tempdir )
140215        # keep a strong reference to shutil.rmtree(), since the finalizer 
141216        # can be called late during Python shutdown 
0 commit comments