Skip to content

Commit 3a536f0

Browse files
committed
fix: database lock handling
1 parent a40b303 commit 3a536f0

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

cve_bin_tool/cvedb.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from cve_bin_tool.error_handler import ERROR_CODES, CVEDBError, ErrorMode, SigningError
3535
from cve_bin_tool.fetch_json_db import Fetch_JSON_DB
3636
from cve_bin_tool.log import LOGGER
37-
from cve_bin_tool.util import make_http_requests
37+
from cve_bin_tool.util import handle_database_lock, make_http_requests
3838
from cve_bin_tool.version import check_latest_version
3939

4040
logging.basicConfig(level=logging.DEBUG)
@@ -297,6 +297,7 @@ async def refresh(self) -> None:
297297

298298
await self.get_data()
299299

300+
@handle_database_lock
300301
def refresh_cache_and_update_db(self) -> None:
301302
"""Refresh cached NVD and update CVE database with latest data."""
302303
self.LOGGER.debug("Updating CVE data. This will take a few minutes.")
@@ -756,6 +757,7 @@ def update_vendors(self, cve_data):
756757

757758
return updated_severity, updated_affected
758759

760+
@handle_database_lock
759761
def db_open_and_get_cursor(self) -> sqlite3.Cursor:
760762
"""Opens connection to sqlite database, returns cursor object."""
761763

@@ -901,6 +903,7 @@ def delete_old_files_if_exists(self, path):
901903
if (path / "metadata.json").exists():
902904
Path.unlink(path / "metadata.json")
903905

906+
@handle_database_lock
904907
def db_to_json(self, path, private_key, passphrase):
905908
"""Create JSON of all records in all database tables."""
906909
if private_key and not passphrase:
@@ -1052,6 +1055,7 @@ def json_to_db(self, cursor, db_column, json_data):
10521055
elif db_column == "metrics":
10531056
cursor.executemany(self.INSERT_QUERIES["insert_metrics"], values)
10541057

1058+
@handle_database_lock
10551059
def json_to_db_wrapper(self, path, pubkey, ignore_signature, log_signature_error):
10561060
"""Initialize the process wrapper to insert records into database from JSON."""
10571061
try:

cve_bin_tool/util.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
from __future__ import annotations
77

88
import fnmatch
9+
import functools
910
import os
1011
import re
1112
import sys
1213
from enum import Enum
1314
from pathlib import Path
15+
from sqlite3 import OperationalError
1416
from typing import DefaultDict, Iterator, List, NamedTuple, Pattern, Set, Union
1517

1618
import requests
@@ -560,3 +562,26 @@ def decode_cpe22(cpe22) -> list:
560562
def windows_fixup(filename):
561563
"""Replace colon and backslash in filename to avoid a failure on Windows"""
562564
return filename.replace(":", "_").replace("\\", "_")
565+
566+
567+
def handle_database_lock(func):
568+
"""Handle sqlite database lock error and print documentation link for user"""
569+
570+
is_executed_in_pytest: bool = "pytest" in sys.modules
571+
572+
@functools.wraps(func)
573+
def wrapper(*args, **kwargs):
574+
try:
575+
return func(*args, **kwargs)
576+
except OperationalError:
577+
if not is_executed_in_pytest:
578+
LOGGER.error(
579+
"An OperationalError was raised. If you are trying to launch multiple scans in parallel,"
580+
" please refer to this page: "
581+
"https://cve-bin-tool.readthedocs.io/en/latest/how_to_guides/multiple_scans_at_once.html"
582+
)
583+
sys.exit(1)
584+
else:
585+
raise # decorator should not affect other test cases
586+
587+
return wrapper

cve_bin_tool/version_signature.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from pathlib import Path
1010

1111
from cve_bin_tool.cvedb import DISK_LOCATION_DEFAULT
12+
from cve_bin_tool.util import handle_database_lock
1213

1314

1415
class InvalidVersionSignatureTable(ValueError):
@@ -59,6 +60,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
5960
"""Closes connection to sqlite database."""
6061
self.close()
6162

63+
@handle_database_lock
6264
def get_mapping_data(self):
6365
"""
6466
Returns a version map associated with the specified checker. Also takes care of updating

0 commit comments

Comments
 (0)