Tribler / tribler

Privacy enhanced BitTorrent client with P2P content discovery
https://www.tribler.org
GNU General Public License v3.0
4.74k stars 445 forks source link

[7.13.2] PermissionError when unlinking processes.sqlite "The process cannot access the file because it is being used by another process" #7931

Closed kozlovsky closed 3 months ago

kozlovsky commented 3 months ago
Traceback (most recent call last):
  File "tribler\core\utilities\process_manager\manager.py", line 92, in connect
sqlite3.OperationalError: database is locked
  During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "run_tribler.py", line 109, in <module>
  File "tribler\core\start_core.py", line 191, in run_core
  File "tribler\core\utilities\process_manager\manager.py", line 40, in setup_process_manager
  File "tribler\core\utilities\process_manager\utils.py", line 29, in new_method
  File "tribler\core\utilities\process_manager\manager.py", line 59, in setup_current_process
  File "contextlib.py", line 113, in __enter__
  File "tribler\core\utilities\process_manager\manager.py", line 108, in connect
  File "pathlib.py", line 1321, in unlink

Here:

    @contextmanager
    def connect(self) -> ContextManager[sqlite3.Connection]:
        ...
        connection = None
        try:
            ...
        except Exception as e:
            logger.exception(f'{e.__class__.__name__}: {e}')

            if connection:
                connection.close()

            if isinstance(e, sqlite3.DatabaseError):
                self.db_filepath.unlink(missing_ok=True)  # <-- here

            if isinstance(e, sqlite3.OperationalError) and str(e) == 'unable to open database file':
                ...

            raise

The reason for the error is that OperationalError is a subclass of DatabaseError. Therefore, the condition if isinstance(e, sqlite3.DatabaseError) mistakenly handles OperationalError as well just as a generic DatabaseError.

The possible solution is to swap handling of OperationalError and DatabaseError to handle all cases of OperationalError first. Also it may be good to wrap the unlink call in try/except to suppress the possible PermissionError.

sentry-for-tribler[bot] commented 3 months ago

Sentry issue: TRIBLER-1KW

kozlovsky commented 3 months ago

Fixed by #7932