}
#else
+
++/* Issue #25003: Don' use getentropy() on Solaris (available since
++ * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
+#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
+#define PY_GETRANDOM 1
+
+static int
+py_getrandom(void *buffer, Py_ssize_t size, int raise)
+{
+ /* Is getrandom() supported by the running kernel?
+ * Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */
+ static int getrandom_works = 1;
+ /* Use non-blocking /dev/urandom device. On Linux at boot, the getrandom()
+ * syscall blocks until /dev/urandom is initialized with enough entropy. */
+ const int flags = 0;
+ int n;
+
+ if (!getrandom_works)
+ return 0;
+
+ while (0 < size) {
+ errno = 0;
+
+#ifdef HAVE_GETRANDOM
+ if (raise) {
+ Py_BEGIN_ALLOW_THREADS
+ n = getrandom(buffer, size, flags);
+ Py_END_ALLOW_THREADS
+ }
+ else {
+ n = getrandom(buffer, size, flags);
+ }
+#else
+ /* On Linux, use the syscall() function because the GNU libc doesn't
+ * expose the Linux getrandom() syscall yet. See:
+ * https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */
+ if (raise) {
+ Py_BEGIN_ALLOW_THREADS
+ n = syscall(SYS_getrandom, buffer, size, flags);
+ Py_END_ALLOW_THREADS
+ }
+ else {
+ n = syscall(SYS_getrandom, buffer, size, flags);
+ }
+#endif
+
+ if (n < 0) {
+ if (errno == ENOSYS) {
+ getrandom_works = 0;
+ return 0;
+ }
+
+ if (errno == EINTR) {
+ if (PyErr_CheckSignals()) {
+ if (!raise)
+ Py_FatalError("getrandom() interrupted by a signal");
+ return -1;
+ }
+ /* retry getrandom() */
+ continue;
+ }
+
+ if (raise)
+ PyErr_SetFromErrno(PyExc_OSError);
+ else
+ Py_FatalError("getrandom() failed");
+ return -1;
+ }
+
+ buffer += n;
+ size -= n;
+ }
+ return 1;
+}
+#endif
+
static struct {
int fd;
dev_t st_dev;