-
-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Race condition in os.makedirs #46016
Comments
There appears to be a race condition in os.makedirs. Suppose two |
I don't think os.makedirs() can do anything here. It should be caller's |
The only thing I found in the bug database concerning os.makedirs was I started writing my own, which was basically just os.makedirs but I think os.makedirs can be fixed by making what is now its recursive |
I think we can fix this as follows: whenever it calls os.mkdir() and an Moreover, I'd like to do this for the ultimate path to be created as I think it should still fail if the path exists as a file though. (Or Patch welcome! I think this is a feature request and hence should only be fixed in 2.6. |
Can you rephrase this as svn diff output? Also, mkdir() is a confusing name for the helper -- I'd call it |
Yes, I'm really combining two things here - the race condition, which I I have not produced a proper Python patch before and I have other things |
Attached is an svn diff against the trunk. I was looking at os.py from The attached patch renames the existing mkdir to _mkdir, and creates a By simply using the new versions as before, one obtains the old I have updated the documentation also but I don't really know what I'm |
I should add that the new parameter is called "excl" by analogy with the Also, I'm not absolutely certain about the test for which exceptions e.errno == errno.EEXIST and path.isdir (name) This will not work if errno is set to something other than EEXIST when It should be safe to drop the errno check altogether, and I'm starting So the if statement would be: if excl or not path.isdir (name):
raise |
Here's the version of this that I've been using for almost a decade now: http://allmydata.org/trac/pyutil/browser/pyutil/pyutil/fileutil.py?rev=127#L241 Actually I used to have a bigger version that could optionally require def make_dirs(dirname, mode=0777):
"""
An idempotent version of os.makedirs(). If the dir already exists, do
nothing and return without raising an exception. If this call
creates the
dir, return without raising an exception. If there is an error that
prevents creation or if the directory gets deleted after make_dirs()
creates
it and before make_dirs() checks that it exists, raise an exception.
"""
tx = None
try:
os.makedirs(dirname, mode)
except OSError, x:
tx = x
if not os.path.isdir(dirname):
if tx:
raise tx
raise exceptions.IOError, "unknown error prevented creation of
directory, or deleted the directory immediately after creation: %s" %
dirname # careful not to construct an IOError with a 2-tuple, as that
has a special meaning... |
This is again being discussed in bpo-9299. |
The precipitating issue for this and bpo-9299 are different: parent race leading to error versus tail existence leading to error. However, both patches address both issues. See bpo-9299 for my comparison of this patch and that. I am consolidating nosy lists there. Perhaps most/all further discussion should be directed there. |
Isaac, thank you for the report and patch. With more attention, this might have been tweaked and applied a couple of years ago. We are trying to get better at timely responses. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: