19
19
from . import process
20
20
21
21
__all__ = [
22
- 'sub_debug' , 'debug' , 'info' , 'sub_warning' , 'get_logger' ,
22
+ 'sub_debug' , 'debug' , 'info' , 'sub_warning' , 'warn' , ' get_logger' ,
23
23
'log_to_stderr' , 'get_temp_dir' , 'register_after_fork' ,
24
24
'is_exiting' , 'Finalize' , 'ForkAwareThreadLock' , 'ForkAwareLocal' ,
25
25
'close_all_fds_except' , 'SUBDEBUG' , 'SUBWARNING' ,
34
34
DEBUG = 10
35
35
INFO = 20
36
36
SUBWARNING = 25
37
+ WARNING = 30
37
38
38
39
LOGGER_NAME = 'multiprocessing'
39
40
DEFAULT_LOGGING_FORMAT = '[%(levelname)s/%(processName)s] %(message)s'
@@ -53,6 +54,10 @@ def info(msg, *args):
53
54
if _logger :
54
55
_logger .log (INFO , msg , * args , stacklevel = 2 )
55
56
57
+ def warn (msg , * args ):
58
+ if _logger :
59
+ _logger .log (WARNING , msg , * args , stacklevel = 2 )
60
+
56
61
def sub_warning (msg , * args ):
57
62
if _logger :
58
63
_logger .log (SUBWARNING , msg , * args , stacklevel = 2 )
@@ -121,17 +126,17 @@ def is_abstract_socket_namespace(address):
121
126
# Function returning a temp directory which will be removed on exit
122
127
#
123
128
124
- # Maximum length of a socket file path is usually between 92 and 108 [1].
125
- # BSD-based operating systems usually use 104 (OpenBSD, FreeBSD, macOS)
126
- # and Linux uses 108 [2] .
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 .
127
132
#
128
133
# [1]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_un.h.html
129
134
# [2]: https://man7.org/linux/man-pages/man7/unix.7.html.
130
135
131
136
if sys .platform == 'linux' :
132
- _SUN_PATH_MAX = 104
133
- elif sys .platform .startswith (('openbsd' , 'freebsd' )):
134
137
_SUN_PATH_MAX = 108
138
+ elif sys .platform .startswith (('openbsd' , 'freebsd' )):
139
+ _SUN_PATH_MAX = 104
135
140
else :
136
141
# On Windows platforms, we do not create AF_UNIX sockets.
137
142
_SUN_PATH_MAX = None if os .name == 'nt' else 92
@@ -145,31 +150,67 @@ def _remove_temp_dir(rmtree, tempdir):
145
150
if current_process is not None :
146
151
current_process ._config ['tempdir' ] = None
147
152
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 %r will not be usable for "
196
+ "creating socket files and no usable system-wide temporary "
197
+ "directory was found in %r" , 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
+
148
207
def get_temp_dir ():
149
208
# get name of a temp directory which will be automatically cleaned up
150
209
tempdir = process .current_process ()._config .get ('tempdir' )
151
210
if tempdir is None :
152
211
import shutil , tempfile
153
- if os .name == 'nt' :
154
- tempdir = tempfile .mkdtemp (prefix = 'pymp-' )
155
- else :
156
- # Most of the time, the root temporary directory is /tmp, and thus
157
- # listener sockets files "$TMPDIR/pymp-XXXXXXXX/sock-XXXXXXXX"
158
- # do not have a path length exceeding SUN_PATH_MAX.
159
- #
160
- # If users specify their own temporary directory, we may be unable
161
- # to create those files. Therefore, we fall back to the system-wide
162
- # temporary directory /tmp, assumed to exist on POSIX systems.
163
- #
164
- # See https://github.com/python/cpython/issues/132124.
165
- base_tempdir = tempfile .gettempdir ()
166
- # len(base_tempdir) + len('/pymp-XXXXXXXX') + len('/sock-XXXXXXXX')
167
- sun_path_len = len (base_tempdir ) + 14 + 14
168
- if sun_path_len > _SUN_PATH_MAX :
169
- # fallback to the system-wide temporary directory,
170
- # ignoring environment variables.
171
- base_tempdir = '/tmp'
172
- tempdir = tempfile .mkdtemp (prefix = 'pymp-' , dir = base_tempdir )
212
+ base_tempdir = _get_base_temp_dir (tempfile )
213
+ tempdir = tempfile .mkdtemp (prefix = 'pymp-' , dir = base_tempdir )
173
214
info ('created temp directory %s' , tempdir )
174
215
# keep a strong reference to shutil.rmtree(), since the finalizer
175
216
# can be called late during Python shutdown
0 commit comments