@@ -90,6 +90,7 @@ vms_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
9090
9191
9292#if !defined(MS_WINDOWS ) && !defined(__VMS )
93+ static int urandom_fd = -1 ;
9394
9495/* Read size bytes from /dev/urandom into buffer.
9596 Call Py_FatalError() on error. */
@@ -133,18 +134,30 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
133134 if (size <= 0 )
134135 return 0 ;
135136
136- Py_BEGIN_ALLOW_THREADS
137- fd = _Py_open ("/dev/urandom" , O_RDONLY );
138- Py_END_ALLOW_THREADS
139- if (fd < 0 )
140- {
141- if (errno == ENOENT || errno == ENXIO ||
142- errno == ENODEV || errno == EACCES )
143- PyErr_SetString (PyExc_NotImplementedError ,
144- "/dev/urandom (or equivalent) not found" );
137+ if (urandom_fd >= 0 )
138+ fd = urandom_fd ;
139+ else {
140+ Py_BEGIN_ALLOW_THREADS
141+ fd = _Py_open ("/dev/urandom" , O_RDONLY );
142+ Py_END_ALLOW_THREADS
143+ if (fd < 0 )
144+ {
145+ if (errno == ENOENT || errno == ENXIO ||
146+ errno == ENODEV || errno == EACCES )
147+ PyErr_SetString (PyExc_NotImplementedError ,
148+ "/dev/urandom (or equivalent) not found" );
149+ else
150+ PyErr_SetFromErrno (PyExc_OSError );
151+ return -1 ;
152+ }
153+ if (urandom_fd >= 0 ) {
154+ /* urandom_fd was initialized by another thread while we were
155+ not holding the GIL, keep it. */
156+ close (fd );
157+ fd = urandom_fd ;
158+ }
145159 else
146- PyErr_SetFromErrno (PyExc_OSError );
147- return -1 ;
160+ urandom_fd = fd ;
148161 }
149162
150163 Py_BEGIN_ALLOW_THREADS
@@ -168,12 +181,20 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
168181 PyErr_Format (PyExc_RuntimeError ,
169182 "Failed to read %zi bytes from /dev/urandom" ,
170183 size );
171- close (fd );
172184 return -1 ;
173185 }
174- close (fd );
175186 return 0 ;
176187}
188+
189+ static void
190+ dev_urandom_close (void )
191+ {
192+ if (urandom_fd >= 0 ) {
193+ close (urandom_fd );
194+ urandom_fd = -1 ;
195+ }
196+ }
197+
177198#endif /* !defined(MS_WINDOWS) && !defined(__VMS) */
178199
179200/* Fill buffer with pseudo-random bytes generated by a linear congruent
@@ -271,3 +292,11 @@ _PyRandom_Init(void)
271292#endif
272293 }
273294}
295+
296+ void
297+ _PyRandom_Fini (void )
298+ {
299+ #if !defined(MS_WINDOWS ) && !defined(__VMS )
300+ dev_urandom_close ();
301+ #endif
302+ }
0 commit comments