
Hi, I've got strange issue. Its sometimes produced on PyPy + setuptools while creating virtualenv environment. On CPython (on the same hosts) its not occurs. All recent versions of PyPy (1.9, 2.0b{1,2}, 2.0.2) are affected, but frequency is decreased with version grow (on 2.0.2 we got it only several times when on 2.0b1 it was frequent). Symptoms: On heavy loaded linux hosts (tests build machines with Debian GNU/Linux 6.0 x86_64) sometimes os.listdir for PyPy base directory (/usr/pypy-2.0/lib-python/2.7) produces OSError: [Errno 11] Resource temporarily unavailable. It is strange because all system calls (which os.listdir called) unable to emit (due to man pages) EAGAIN error. Host filesystem is ext4 (not nfs). How to reproduce: we have no idea how to reliably reproduce it, but it sometimes occurs in heavy loaded environment and only with os.listdir inside of setuptools. ----------------------------------------------------------------------------------------------------------------- 13:01:26,594 INFO - Exception: 13:01:26,594 INFO - Traceback (most recent call last): 13:01:26,594 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/pip-1.3.1-py2.7.egg/pip/basecommand.py", line 139, in main 13:01:26,594 INFO - status = self.run(options, args) 13:01:26,594 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/pip-1.3.1-py2.7.egg/pip/commands/install.py", line 266, in run 13:01:26,594 INFO - requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle) 13:01:26,594 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/pip-1.3.1-py2.7.egg/pip/req.py", line 954, in prepare_files 13:01:26,594 INFO - req_to_install.check_if_exists() 13:01:26,594 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/pip-1.3.1-py2.7.egg/pip/req.py", line 686, in check_if_exists 13:01:26,594 INFO - self.satisfied_by = pkg_resources.get_distribution(self.req) 13:01:26,594 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/setuptools-0.6c11-py2.7.egg/pkg_resources.py", line 311, in get_distribution 13:01:26,594 INFO - if isinstance(dist,Requirement): dist = get_provider(dist) 13:01:26,594 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/setuptools-0.6c11-py2.7.egg/pkg_resources.py", line 197, in get_provider 13:01:26,594 INFO - return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] 13:01:26,594 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/setuptools-0.6c11-py2.7.egg/pkg_resources.py", line 666, in require 13:01:26,594 INFO - needed = self.resolve(parse_requirements(requirements)) 13:01:26,594 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/setuptools-0.6c11-py2.7.egg/pkg_resources.py", line 562, in resolve 13:01:26,594 INFO - env = Environment(self.entries) 13:01:26,594 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/setuptools-0.6c11-py2.7.egg/pkg_resources.py", line 722, in __init__ 13:01:26,594 INFO - self.scan(search_path) 13:01:26,595 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/setuptools-0.6c11-py2.7.egg/pkg_resources.py", line 751, in scan 13:01:26,595 INFO - for dist in find_distributions(item): 13:01:26,595 INFO - File "/var/lib/buildagent/workspace/52609/env/site-packages/setuptools-0.6c11-py2.7.egg/pkg_resources.py", line 1700, in find_on_path 13:01:26,595 INFO - for entry in os.listdir(path_item): 13:01:26,595 INFO - OSError: [Errno 11] Resource temporarily unavailable: '/usr/pypy-2.0/lib-python/2.7'

Hi Vasily, On Mon, Jun 24, 2013 at 2:28 PM, Vasily Evseenko <svpcom@gmail.com> wrote:
Shooting in the dark, but one possible reading of the man page shows that when readdir() returns a non-null pointer, the value of errno might be randomly modified. It could be the case that an ultimately successful readdir() was done by two system calls, the first one being interrupted with EAGAIN. If that's correct, it's fixed in 83f89665175e, but you have to try it out... A bientôt, Armin.

On Mon, Jun 24, 2013 at 06:05:39PM +0200, Armin Rigo wrote:
Yes, this is true and bit me in a different context just over a year ago: http://comments.gmane.org/gmane.os.openbsd.tech/27909 Philip Guenther's message is worth reading to get some idea of the particular, quasi-legal language, that POSiX uses (and that confused me). Laurie -- Personal http://tratt.net/laurie/ Software Development Team http://soft-dev.org/ https://github.com/ltratt http://twitter.com/laurencetratt

Hi Laurence, On Tue, Jun 25, 2013 at 11:14 AM, Laurence Tratt <laurie@tratt.net> wrote:
According to these mails, the issue you've hit is different: what occurs to errno if readdir() returns NULL. This is indeed strange but documented. But what occurs to errno if readdir() does *not* return NULL? I thought that errno would not be modified in this case, but as far as I know the Posix man page is silent on the subject, and it might be the cause of Vasily's report. A bientôt, Armin.

On Tue, Jun 25, 2013 at 01:51:48PM +0200, Armin Rigo wrote:
The point that eventually became clear to me is that returning NULL and setting errno are not necessarily connected, which was the original mistake I made. errors can happen (and errno set) even if readdir hasn't hit the end of the directory (so NULL need not be returned). Linux's man page is, unusually, clearer than OpenBSD's in this regard, though it's so long and lawyerly that it's still hard to work out what's going on! I had to read OpenBSD's source code to work this out last year :/ Laurie -- Personal http://tratt.net/laurie/ Software Development Team http://soft-dev.org/ https://github.com/ltratt http://twitter.com/laurencetratt

On Tue, Jun 25, 2013 at 11:34:03PM +0200, Armin Rigo wrote:
Sorry, I don't follow you. As far as I know the Linux man page is not clear about what occurs to errno if readdir() doesn't return NULL...
Exactly :) My reading of it is that readdir returns: NULL and sets errno if an error occurred; NULL and doesn't change errno if end of directory was reached; non-NULL and no guarantees about errno if it's half-way through reading a directory and no errors occurred. I came to the conclusion that I had to be defensive and do the following: errno must be set to 0 before readdir; only if NULL is returned can errno be checked to see its value. [When I read through the OpenBSD source, the implementation happens to define that if non-NULL is returned, errno isn't fiddled about with (unless getdirentries is buggy, which I didn't check!). The documentation does not mention anything about this, so I think one has to assume that all bets are off, particularly on other OS's.] This all seems a big mess to me, but since I changed my code, I've had no problems with readdir (on OpenBSD or Linux), so I assume my defensive action was successful... Laurie -- Personal http://tratt.net/laurie/ Software Development Team http://soft-dev.org/ https://github.com/ltratt http://twitter.com/laurencetratt

Hi Laurence, On Wed, Jun 26, 2013 at 12:03 AM, Laurence Tratt <laurie@tratt.net> wrote:
Ok, thanks :-) I really have to wonder why Posix didn't say that readdir() returning NULL on end-of-directory simply *sets* errno to 0. Or even why it wouldn't allow both behaviors (it doesn't change anything if you set errno to 0 yourself before, and setting it to 0 is what you need in all practical cases), recommend the saner one, and so gradually phase out the old behavior. I even wonder why some systems don't implement a "readdir1()" function that does "errno=0; readdir()"... But enough pointless ranting :-) A bientôt, Armin.

Hi Vasily, On Mon, Jun 24, 2013 at 2:28 PM, Vasily Evseenko <svpcom@gmail.com> wrote:
Shooting in the dark, but one possible reading of the man page shows that when readdir() returns a non-null pointer, the value of errno might be randomly modified. It could be the case that an ultimately successful readdir() was done by two system calls, the first one being interrupted with EAGAIN. If that's correct, it's fixed in 83f89665175e, but you have to try it out... A bientôt, Armin.

On Mon, Jun 24, 2013 at 06:05:39PM +0200, Armin Rigo wrote:
Yes, this is true and bit me in a different context just over a year ago: http://comments.gmane.org/gmane.os.openbsd.tech/27909 Philip Guenther's message is worth reading to get some idea of the particular, quasi-legal language, that POSiX uses (and that confused me). Laurie -- Personal http://tratt.net/laurie/ Software Development Team http://soft-dev.org/ https://github.com/ltratt http://twitter.com/laurencetratt

Hi Laurence, On Tue, Jun 25, 2013 at 11:14 AM, Laurence Tratt <laurie@tratt.net> wrote:
According to these mails, the issue you've hit is different: what occurs to errno if readdir() returns NULL. This is indeed strange but documented. But what occurs to errno if readdir() does *not* return NULL? I thought that errno would not be modified in this case, but as far as I know the Posix man page is silent on the subject, and it might be the cause of Vasily's report. A bientôt, Armin.

On Tue, Jun 25, 2013 at 01:51:48PM +0200, Armin Rigo wrote:
The point that eventually became clear to me is that returning NULL and setting errno are not necessarily connected, which was the original mistake I made. errors can happen (and errno set) even if readdir hasn't hit the end of the directory (so NULL need not be returned). Linux's man page is, unusually, clearer than OpenBSD's in this regard, though it's so long and lawyerly that it's still hard to work out what's going on! I had to read OpenBSD's source code to work this out last year :/ Laurie -- Personal http://tratt.net/laurie/ Software Development Team http://soft-dev.org/ https://github.com/ltratt http://twitter.com/laurencetratt

On Tue, Jun 25, 2013 at 11:34:03PM +0200, Armin Rigo wrote:
Sorry, I don't follow you. As far as I know the Linux man page is not clear about what occurs to errno if readdir() doesn't return NULL...
Exactly :) My reading of it is that readdir returns: NULL and sets errno if an error occurred; NULL and doesn't change errno if end of directory was reached; non-NULL and no guarantees about errno if it's half-way through reading a directory and no errors occurred. I came to the conclusion that I had to be defensive and do the following: errno must be set to 0 before readdir; only if NULL is returned can errno be checked to see its value. [When I read through the OpenBSD source, the implementation happens to define that if non-NULL is returned, errno isn't fiddled about with (unless getdirentries is buggy, which I didn't check!). The documentation does not mention anything about this, so I think one has to assume that all bets are off, particularly on other OS's.] This all seems a big mess to me, but since I changed my code, I've had no problems with readdir (on OpenBSD or Linux), so I assume my defensive action was successful... Laurie -- Personal http://tratt.net/laurie/ Software Development Team http://soft-dev.org/ https://github.com/ltratt http://twitter.com/laurencetratt

Hi Laurence, On Wed, Jun 26, 2013 at 12:03 AM, Laurence Tratt <laurie@tratt.net> wrote:
Ok, thanks :-) I really have to wonder why Posix didn't say that readdir() returning NULL on end-of-directory simply *sets* errno to 0. Or even why it wouldn't allow both behaviors (it doesn't change anything if you set errno to 0 yourself before, and setting it to 0 is what you need in all practical cases), recommend the saner one, and so gradually phase out the old behavior. I even wonder why some systems don't implement a "readdir1()" function that does "errno=0; readdir()"... But enough pointless ranting :-) A bientôt, Armin.
participants (3)
-
Armin Rigo
-
Laurence Tratt
-
Vasily Evseenko