changeset: 85199:fe949918616c parent: 85197:96c51207e7cd parent: 85198:193bcc12575d user: Antoine Pitrou date: Fri Aug 16 20:49:32 2013 +0200 files: Lib/test/test_os.py Misc/NEWS Python/random.c description: Issue #18756: Improve error reporting in os.urandom() when the failure is due to something else than /dev/urandom not existing. diff -r 96c51207e7cd -r fe949918616c Lib/test/test_os.py --- a/Lib/test/test_os.py Fri Aug 16 21:33:27 2013 +0300 +++ b/Lib/test/test_os.py Fri Aug 16 20:49:32 2013 +0200 @@ -30,6 +30,11 @@ 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 @@ 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 -r 96c51207e7cd -r fe949918616c Misc/NEWS --- a/Misc/NEWS Fri Aug 16 21:33:27 2013 +0300 +++ b/Misc/NEWS Fri Aug 16 20:49:32 2013 +0200 @@ -28,6 +28,10 @@ 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 -r 96c51207e7cd -r fe949918616c Python/random.c --- a/Python/random.c Fri Aug 16 21:33:27 2013 +0300 +++ b/Python/random.c Fri Aug 16 20:49:32 2013 +0200 @@ -138,8 +138,12 @@ 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; }