-
Notifications
You must be signed in to change notification settings - Fork 1
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
Changes from 10 commits
baa3462
2c88eac
9e8869b
02a82f7
51da02b
372c6b9
f51a58e
4af47c3
98745fa
c4b4e97
020034f
3fafa21
ea85fae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,10 +5,11 @@ | |
import logging | ||
import os | ||
import shutil | ||
import stat | ||
from concurrent.futures import ThreadPoolExecutor | ||
from dataclasses import dataclass, replace | ||
from pathlib import Path, PurePath | ||
from typing import List, Optional | ||
from typing import Any, List, Optional, Union | ||
|
||
import aiofiles | ||
|
||
|
@@ -203,10 +204,23 @@ async def get_filestatus(self, path: PurePath) -> FileStatus: | |
def _remove(self, path: PurePath) -> None: | ||
concrete_path = Path(path) | ||
if concrete_path.is_dir(): | ||
shutil.rmtree(concrete_path) | ||
shutil.rmtree(concrete_path, onerror=self._handle_rmtree_error) | ||
else: | ||
concrete_path.unlink() | ||
|
||
def _handle_rmtree_error( | ||
self, func: Any, path: Union[str, os.PathLike], exc_info: Any | ||
) -> Any: | ||
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): | ||
logger.warning("Access error") | ||
# Try to change the permission of file | ||
os.chmod(path, stat.S_IWUSR) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
# call the calling function again | ||
func(path) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 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 . There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding was that the call on the line 222 would have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dalazx Answering your question, there is no recursion. But we can get a leak of the file descriptor if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. got it. thanks for the explanation guys. |
||
|
||
async def remove(self, path: PurePath) -> None: | ||
await self._loop.run_in_executor(self._executor, self._remove, path) | ||
|
||
|
There was a problem hiding this comment.
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.There was a problem hiding this comment.
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.