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

Add error logging and recovery #94

Merged
merged 13 commits into from
May 13, 2019
Merged

Add error logging and recovery #94

merged 13 commits into from
May 13, 2019

Conversation

anayden
Copy link
Contributor

@anayden anayden commented May 7, 2019

This is to investigate the issue in neuro-inc/neuro-cli#752

logger.warning("Handling Error for file %s", path)
logger.warning(exc_info)
# Check if file access issue
if not os.access(path, os.W_OK):
Copy link
Contributor

Choose a reason for hiding this comment

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

The error handler can be called for different functions: scandir, open, stat, rmdir, unlink. In some cases the function is failed because the path is absent or is nor accessible (for example because the parent directory is absent or non-readable). os.access() will fail in tat case as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree with you, but this code is only temporary needed to troubleshoot the issue with rmtree. I don't plan to use it as a permanent handler.

if not os.access(path, os.W_OK):
logger.warning("Access error")
# Try to change the permission of file
os.chmod(path, stat.S_IWUSR)
Copy link
Contributor

Choose a reason for hiding this comment

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

You may need to change the mode of the parent too. See python/cpython#10320.

# Try to change the permission of file
os.chmod(path, stat.S_IWUSR)
# call the calling function again
func(path)
Copy link
Contributor

Choose a reason for hiding this comment

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

The function may need other arguments (for example dir_fd). And calling it will not help if it is scandir or stat.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as above: this is a temporary troubleshooting handler that is supposed to work with rmtree only.

@serhiy-storchaka
Copy link
Contributor

See my attempt to fix the similar problem for TemporaryDirectory: python/cpython#10320. That PR has not been merged yet because I need to test it on Windows and analyze it for the case of possible infinite recursion.

@anayden
Copy link
Contributor Author

anayden commented May 8, 2019

@serhiy-storchaka any ideas how to better handle this (4af47c3#diff-28f724c04d913ea0e52fd0278f9b4f8fR211)?

My solutions looks ugly and perhaps I'm missing something.

@serhiy-storchaka
Copy link
Contributor

The type of the second parameter is Union[str, os.PathLike]. But you can use Any as well.

@serhiy-storchaka
Copy link
Contributor

You can use make _lint for local checking.

@anayden
Copy link
Contributor Author

anayden commented May 8, 2019

You can use make _lint for local checking.

I do, but I somehow missed the last issue. My bad.

@anayden
Copy link
Contributor Author

anayden commented May 8, 2019

@serhiy-storchaka does the code look reasonably good to you? I only want to get more debugging output here for further fixes.

@serhiy-storchaka
Copy link
Contributor

If you want to just log the error, it is enough to log it and reraise the exception. Calling the failed function again not always has effect. But I think this will not make the situation worse.

# Try to change the permission of file
os.chmod(path, stat.S_IWUSR)
# call the calling function again
func(path)
Copy link
Collaborator

Choose a reason for hiding this comment

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

won't this result in the call stack depletion? should we reraise the exception instead as @serhiy-storchaka has suggested?

Copy link
Contributor

Choose a reason for hiding this comment

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

On other hand, if just log and reraise the error -- this does not differ from catching and logging error outside of the rmtree().

But if the goal is fixing the error, calling the function again is not enough. You will need more complex solution like in python/cpython#10320 .

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My understanding was that the call on the line 222 would have onerror=None and hence raise the exception on error. Isn't it the case?

Copy link
Contributor

Choose a reason for hiding this comment

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

@dalazx Answering your question, there is no recursion. func is not recursive and the onerror handler is not called for the exception raised in the onerror handler.

But we can get a leak of the file descriptor if func is os.open and the repeated call is finished successfully for some reasons.

Copy link
Collaborator

Choose a reason for hiding this comment

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

got it. thanks for the explanation guys.

# Debug logging
path = e.filename
parent_path = os.path.dirname(path)
path_access_ok = os.access(path, os.W_OK)
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be nice to output a mode.

try:
    path_mode = f"{os.stat(path).st_mode:03o}"
except OSError:
    path_mode = '?'

path_access_ok = os.access(path, os.W_OK)
parent_path_access_ok = os.access(parent_path, os.W_OK)
logger.warning(
f"OSError for path %s, access = %s parent_access = %s",
Copy link
Contributor

Choose a reason for hiding this comment

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

Add also the error message.

Either use the f-string for formatting the whole message or do not use the f prefix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean e.strerror?

Copy link
Contributor

@serhiy-storchaka serhiy-storchaka May 13, 2019

Choose a reason for hiding this comment

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

And the errno attribute. Or better errno.errorcode.get(err.errno, err.errno).

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you mean e.strerror?

str(e)

@anayden anayden merged commit 2f0ed6f into master May 13, 2019
@asvetlov asvetlov deleted the an/log-rmtree-errors branch August 20, 2020 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants