Skip to content
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

Fix os.makedirs issue in multithreading (#2039) #2093

Merged
merged 3 commits into from
Sep 19, 2017

Conversation

elnikkis
Copy link
Contributor

Description

There is a problem that os.makedirs is not atomic in multithreading.

Motivation and Context

This problem is reported in issue #2039.

Since exist_ok was added in Python 3.2 or later, it cannot be used in Python 2.7, so we need to check OSError.errno that we caught.
But in Python 3.x, os.makedirs raise FileExistsError instead of OSError.
FileExistsError is a subclass of OSError but does not have errno attribute.

Have you tested this? If so, how?

In my environment, it seems to work well.

@mention-bot
Copy link

@elnikkis, thanks for your PR! By analyzing the history of the files in this pull request, we identified @Tarrasch and @adaitche to be potential reviewers.

@kalvdans
Copy link
Contributor

In Python 3.5 on Linux, FileExistsError has the errno attribute. So you can simplify the logic to always catch OSError and unconditionally access err.errno attribute.

Test performed in Ipython:

n [3]: try: os.makedirs("/tmp")
   ...: except Exception as e:
   ...:     a = e
   ...:     

In [4]: a
Out[4]: FileExistsError(17, 'File exists')

In [5]: a.errno
Out[5]: 17

@Tarrasch
Copy link
Contributor

Not sure if this is the same thing, but there's a similar compatibility-hack here: https://github.com/spotify/luigi/blob/master/luigi/lock.py#L125-L129

@kalvdans
Copy link
Contributor

Yes, that hack should also be changed to check errno, to correctly propagate other OSError errors in Python 2.

FileExistsError has the errno attribute.
@elnikkis
Copy link
Contributor Author

FileExistsError has a errno attribute.
It was my missunderstand.
Thank you.

try:
FileNotExistsError
except NameError:
FileNotExistsError = OSError
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To reduce complexity, please use OSError on Python3 as well.

try:
os.makedirs(path)
except FileNotExistsError as err:
# somebody already created the path
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is very helpful explaining why we can ignore the error. Thanks for adding it.

Copy link
Contributor

@kalvdans kalvdans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change looks good to me. I have no merging rights, hopefully one of the main developers also can have a look at it soon.

os.makedirs(path)
except OSError as err:
# somebody already created the path
if err.errno != errno.EEXIST:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo on EEXIST. Should be EXIST

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I didn't expect that. I recant.

@dlstadther
Copy link
Collaborator

If no one else reviews, i'll merge this week.

@dlstadther dlstadther merged commit 275f80c into spotify:master Sep 19, 2017
@dlstadther
Copy link
Collaborator

Sorry for such delay @elnikkis ! Thanks for your first Luigi contribution!

This was referenced Jun 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants