summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2013-08-16 20:49:32 +0200
committerAntoine Pitrou <solipsis@pitrou.net>2013-08-16 20:49:32 +0200
commit95b21460ee7ae6b9b52753cf2509d439bd6a0476 (patch)
tree634b33b58ad03b1498b63d0b40c22ea61203a57e
parent00731e2455e45dadc45ad1ccc4eff95831eb9d65 (diff)
parentec34ab501025f7fd677e0f6b8a8d0c9f960f069f (diff)
downloadcpython-git-95b21460ee7ae6b9b52753cf2509d439bd6a0476.tar.gz
Issue #18756: Improve error reporting in os.urandom() when the failure is due to something else than /dev/urandom not existing.
-rw-r--r--Lib/test/test_os.py20
-rw-r--r--Misc/NEWS4
-rw-r--r--Python/random.c8
3 files changed, 30 insertions, 2 deletions
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index eb136676c9..b7796b5607 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -30,6 +30,11 @@ try:
import threading
except ImportError:
threading = None
+try:
+ import resource
+except ImportError:
+ resource = None
+
from test.script_helper import assert_python_ok
with warnings.catch_warnings():
@@ -1010,6 +1015,21 @@ class URandomTests(unittest.TestCase):
data2 = self.get_urandom_subprocess(16)
self.assertNotEqual(data1, data2)
+ @unittest.skipUnless(resource, "test requires the resource module")
+ def test_urandom_failure(self):
+ soft_limit, hard_limit = resource.getrlimit(resource.RLIMIT_NOFILE)
+ resource.setrlimit(resource.RLIMIT_NOFILE, (1, hard_limit))
+ try:
+ with self.assertRaises(OSError) as cm:
+ os.urandom(16)
+ self.assertEqual(cm.exception.errno, errno.EMFILE)
+ finally:
+ # We restore the old limit as soon as possible. If doing it
+ # using addCleanup(), code running in between would fail
+ # creating any file descriptor.
+ resource.setrlimit(resource.RLIMIT_NOFILE, (soft_limit, hard_limit))
+
+
@contextlib.contextmanager
def _execvpe_mockup(defpath=None):
"""
diff --git a/Misc/NEWS b/Misc/NEWS
index d849b51760..31f7b618f0 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -28,6 +28,10 @@ Core and Builtins
Library
-------
+- Issue #18756: Improve error reporting in os.urandom() when the failure
+ is due to something else than /dev/urandom not existing (for example,
+ exhausting the file descriptor limit).
+
- Issue #18673: Add O_TMPFILE to os module. O_TMPFILE requires Linux kernel
3.11 or newer. It's only defined on system with 3.11 uapi headers, too.
diff --git a/Python/random.c b/Python/random.c
index 1ad4c3df7f..709f980dca 100644
--- a/Python/random.c
+++ b/Python/random.c
@@ -138,8 +138,12 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
Py_END_ALLOW_THREADS
if (fd < 0)
{
- PyErr_SetString(PyExc_NotImplementedError,
- "/dev/urandom (or equivalent) not found");
+ if (errno == ENOENT || errno == ENXIO ||
+ errno == ENODEV || errno == EACCES)
+ PyErr_SetString(PyExc_NotImplementedError,
+ "/dev/urandom (or equivalent) not found");
+ else
+ PyErr_SetFromErrno(PyExc_OSError);
return -1;
}