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: Prevent PermissionError during browser cleanup on Windows #48

Closed
wants to merge 0 commits into from

Conversation

Nabeelshar
Copy link

@Nabeelshar Nabeelshar commented Mar 11, 2025

Resolves an issue #44 where temporary browser files remain locked during Python's exit cleanup process, causing PermissionError exceptions. Modified browser management to ensure proper resource release and file handle closure before program termination.

Error addressed:

  • Windows Access denied errors with BrowserMetrics files in temporary directories
  • Improved cleanup handling to prevent locked file exceptions

@thalissonvs
Copy link
Owner

Hi @Nabeelshar, thanks for your contribution! I'll review now

"""
if await self._is_browser_running():
await self._execute_command(BrowserCommands.CLOSE)
self._browser_process_manager.stop_process()

Copy link
Owner

Choose a reason for hiding this comment

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

You can remove these blank lines

@@ -95,6 +97,7 @@ class TempDirectoryManager:
def __init__(self, temp_dir_factory=TemporaryDirectory):
self._temp_dir_factory = temp_dir_factory
self._temp_dirs = []
self._logger = logging.getLogger(__name__)
Copy link
Owner

Choose a reason for hiding this comment

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

Add the logger as a global variable, that way we can use it in any class of this file:

logger = logging.getLogger(__name__)

class ...

self._safe_rmtree(temp_dir.name)
self._temp_dirs = []

def _safe_rmtree(self, path):
Copy link
Owner

Choose a reason for hiding this comment

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

I think you can refactor this to better readability. Here's a suggestion:

def _safe_rmtree(self, path):
  
    if not os.path.exists(path):
        return

    if self._attempt_standard_cleanup(path):
        return

    self._manual_cleanup(path)

def _attempt_standard_cleanup(self, path, max_attempts=3):
    # use recursion here, since there's just 3 iterations, it's more readable
    try:
        shutil.rmtree(path)
        return True
    except (OSError, PermissionError) as e:
        if not max_attempts:
            logger.warning(f"log here") # global logger
            return False
    
        time.sleep(0.5)
        return self._attempt_standard_cleanup(path, max_attempts - 1)

def _manual_cleanup(self, path):
    try:
        self._remove_contents(path)
        
        with suppress(OSError, PermissionError):
            os.rmdir(path)
            
    except Exception as e:
        logger.warning(f"log here")

def _remove_contents(self, path):
    for root, dirs, files in os.walk(path, topdown=False):
        for name in files:
            with suppress(PermissionError, OSError):
                os.unlink(os.path.join(root, name))
                
        for name in dirs:
            with suppress(PermissionError, OSError):
                os.rmdir(os.path.join(root, name))

Be free to make your own ideas, but this method needs to be refactores, it's too large

@thalissonvs thalissonvs linked an issue Mar 11, 2025 that may be closed by this pull request
@codecov-commenter
Copy link

codecov-commenter commented Mar 11, 2025

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

Attention: Patch coverage is 32.43243% with 25 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pydoll/browser/managers.py 30.55% 25 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Flag Coverage Δ
tests 95.72% <32.43%> (-1.59%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pydoll/browser/base.py 97.22% <100.00%> (+0.01%) ⬆️
pydoll/browser/managers.py 77.19% <30.55%> (-21.56%) ⬇️
🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@thalissonvs
Copy link
Owner

Also, please follow the Conventional Commits style; without it, I can't generate the releases. Just undo your commit and commit again with the fix: prefix

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.

PermissionError
3 participants