Skip to content

4651 : adding a change to fix database is locked error #4960

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

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 44 additions & 10 deletions cve_bin_tool/cvedb.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import shutil
import sqlite3
import tempfile
import time
from datetime import date
from os import utime
from pathlib import Path
Expand Down Expand Up @@ -49,6 +50,8 @@
EPSS_METRIC_ID = 1
CVSS_2_METRIC_ID = 2
CVSS_3_METRIC_ID = 3
MAX_RETRIES = 5 # Number of retries before failing
RETRY_DELAY = 0.5 # Initial delay in seconds (will double on each retry)


class CVEDB:
Expand Down Expand Up @@ -764,17 +767,48 @@ def update_vendors(self, cve_data):
return updated_severity, updated_affected

def db_open_and_get_cursor(self) -> sqlite3.Cursor:
"""Opens connection to sqlite database, returns cursor object."""
"""Opens connection to SQLite database with retry logic and cursor existence check."""

if not self.connection:
self.connection = sqlite3.connect(self.dbpath)
if self.connection is not None:
cursor = self.connection.cursor()
if cursor is None:
# if this happens somsething has gone horribly wrong
LOGGER.error("Database cursor does not exist")
raise CVEDBError
return cursor
# If we already have a valid connection, try to use it
if self.connection:
try:
cursor = self.connection.cursor()
if cursor is None:
LOGGER.error("Database cursor does not exist")
raise CVEDBError("Cursor creation failed.")
return cursor
except sqlite3.Error as e:
LOGGER.warning(
f"Existing DB connection failed, retrying from scratch. Error: {e}"
)
self.connection = None # Reset and retry below

retries = 0
while retries < MAX_RETRIES:
try:
self.connection = sqlite3.connect(self.dbpath, timeout=10)
cursor = self.connection.cursor()
if cursor is None:
LOGGER.error("Database cursor does not exist")
raise CVEDBError("Cursor creation failed.")
return cursor
except sqlite3.OperationalError as e:
if "database is locked" in str(e):
retries += 1
wait_time = RETRY_DELAY * (2**retries)
LOGGER.warning(
f"Database locked, retrying in {wait_time:.2f} seconds..."
)
time.sleep(wait_time)
else:
LOGGER.error(f"Database operation failed: {e}")
raise CVEDBError(f"Database operation failed: {e}")
except sqlite3.Error as e:
LOGGER.error(f"Unexpected database error: {e}")
raise CVEDBError(f"Unexpected database error: {e}")

LOGGER.error("Max retries reached. Could not obtain database connection.")
raise CVEDBError("Failed to open database connection after multiple attempts")

def db_close(self) -> None:
"""Closes connection to sqlite database."""
Expand Down
6 changes: 3 additions & 3 deletions cve_bin_tool/extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def __init__(self, logger=None, error_mode=ErrorMode.TruncTrace):
],
MIMES: [
"application/x-tar",
"appication/gzip",
"application/gzip",
],
},
self.extract_file_rpm: {EXTENSIONS: [".rpm"], MIMES: []},
Expand Down Expand Up @@ -261,8 +261,8 @@ async def _extract_through_7z() -> int:
if await aio_inpath("7z"):
return await _extract_through_7z()

# Tarfile wasn't used here because it can't open [.pkg] files directy
# and failed to manage distinct compression types in differnet versions of FreeBSD packages.
# Tarfile wasn't used here because it can't open [.pkg] files directly
# and failed to manage distinct compression types in different versions of FreeBSD packages.
# Reference: https://github.com/intel/cve-bin-tool/pull/1580#discussion_r829346602
if await aio_inpath("tar"):
stdout, stderr, return_code = await aio_run_command(
Expand Down
2 changes: 1 addition & 1 deletion cve_bin_tool/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def filter(self, record):
return record.levelno < self.level


# Rich Handler by default Initalize a Console with stderr stream for logs
# Rich Handler by default Initialize a Console with stderr stream for logs
logging.basicConfig(
level="INFO",
format="%(name)s - %(message)s",
Expand Down
2 changes: 1 addition & 1 deletion cve_bin_tool/output_engine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ def output_pdf(

class OutputEngine:
"""
Class represention of OutputEngine
Class representation of OutputEngine
Attributes:
all_cve_data (dict[ProductInfo, CVEData])
scanned_dir (str)
Expand Down
18 changes: 9 additions & 9 deletions cve_bin_tool/output_engine/html_reports/Example/example.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cve_bin_tool/output_engine/html_reports/js/plotly.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cve_bin_tool/sbom_manager/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def common_prefix_split(self, product, version) -> list[ProductInfo]:
if not found_common_prefix:
# if vendor not found after removing common prefix try splitting it
LOGGER.debug(
f"No Vendor found for {product}, trying splitted product. "
f"No Vendor found for {product}, trying split product. "
"Some results may be inaccurate due to vendor identification limitations."
)
splitted_product = product.split("-")
Expand Down
16 changes: 8 additions & 8 deletions cve_bin_tool/schemas/pom.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@
<xs:complexType name="CiManagement">
<xs:annotation>
<xs:documentation source="version">4.0.0+</xs:documentation>
<xs:documentation source="description"> The <code>&lt;CiManagement&gt;</code> element contains informations required to the continuous integration system of the project. </xs:documentation>
<xs:documentation source="description"> The <code>&lt;CiManagement&gt;</code> element contains information required to the continuous integration system of the project. </xs:documentation>
</xs:annotation>
<xs:all>
<xs:element minOccurs="0" name="system" type="xs:string">
Expand Down Expand Up @@ -397,7 +397,7 @@
<xs:complexType name="Scm">
<xs:annotation>
<xs:documentation source="version">4.0.0+</xs:documentation>
<xs:documentation source="description"> The <code>&lt;scm&gt;</code> element contains informations required to the SCM (Source Control Management) of the project. </xs:documentation>
<xs:documentation source="description"> The <code>&lt;scm&gt;</code> element contains information required to the SCM (Source Control Management) of the project. </xs:documentation>
</xs:annotation>
<xs:all>
<xs:element minOccurs="0" name="connection" type="xs:string">
Expand Down Expand Up @@ -553,7 +553,7 @@
<xs:complexType name="Exclusion">
<xs:annotation>
<xs:documentation source="version">4.0.0+</xs:documentation>
<xs:documentation source="description"> The <code>&lt;exclusion&gt;</code> element contains informations required to exclude an artifact to the project. </xs:documentation>
<xs:documentation source="description"> The <code>&lt;exclusion&gt;</code> element contains information required to exclude an artifact to the project. </xs:documentation>
</xs:annotation>
<xs:all>
<xs:element minOccurs="0" name="artifactId" type="xs:string">
Expand Down Expand Up @@ -1027,7 +1027,7 @@
<xs:complexType name="ReportPlugin">
<xs:annotation>
<xs:documentation source="version">4.0.0+</xs:documentation>
<xs:documentation source="description"> The <code>&lt;plugin&gt;</code> element contains informations required for a report plugin. </xs:documentation>
<xs:documentation source="description"> The <code>&lt;plugin&gt;</code> element contains information required for a report plugin. </xs:documentation>
</xs:annotation>
<xs:all>
<xs:element minOccurs="0" name="groupId" type="xs:string" default="org.apache.maven.plugins">
Expand Down Expand Up @@ -1387,7 +1387,7 @@
<xs:complexType name="BuildBase">
<xs:annotation>
<xs:documentation source="version">3.0.0+</xs:documentation>
<xs:documentation source="description">Generic informations for a build.</xs:documentation>
<xs:documentation source="description">Generic information for a build.</xs:documentation>
</xs:annotation>
<xs:all>
<xs:element minOccurs="0" name="defaultGoal" type="xs:string">
Expand Down Expand Up @@ -1463,7 +1463,7 @@
<xs:complexType name="Plugin">
<xs:annotation>
<xs:documentation source="version">4.0.0+</xs:documentation>
<xs:documentation source="description"> The <code>&lt;plugin&gt;</code> element contains informations required for a plugin. </xs:documentation>
<xs:documentation source="description"> The <code>&lt;plugin&gt;</code> element contains information required for a plugin. </xs:documentation>
</xs:annotation>
<xs:all>
<xs:element minOccurs="0" name="groupId" type="xs:string" default="org.apache.maven.plugins">
Expand Down Expand Up @@ -1545,7 +1545,7 @@
<xs:complexType name="PluginExecution">
<xs:annotation>
<xs:documentation source="version">4.0.0+</xs:documentation>
<xs:documentation source="description"> The <code>&lt;execution&gt;</code> element contains informations required for the execution of a plugin. </xs:documentation>
<xs:documentation source="description"> The <code>&lt;execution&gt;</code> element contains information required for the execution of a plugin. </xs:documentation>
</xs:annotation>
<xs:all>
<xs:element minOccurs="0" name="id" type="xs:string" default="default">
Expand Down Expand Up @@ -1674,7 +1674,7 @@
<xs:complexType name="Build">
<xs:annotation>
<xs:documentation source="version">3.0.0+</xs:documentation>
<xs:documentation source="description"> The <code>&lt;build&gt;</code> element contains informations required to build the project. Default values are defined in Super POM. </xs:documentation>
<xs:documentation source="description"> The <code>&lt;build&gt;</code> element contains information required to build the project. Default values are defined in Super POM. </xs:documentation>
</xs:annotation>
<xs:all>
<xs:element minOccurs="0" name="sourceDirectory" type="xs:string">
Expand Down
6 changes: 3 additions & 3 deletions cve_bin_tool/schemas/swid.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@
Allows any undeclared elements in the SoftwareIdentity element
as long as the element is placed in a different namespace.

As xs:any supercedes an xs:element declaration, this continues
As xs:any supersedes an xs:element declaration, this continues
to support digital signatures using the ds:Signature element:

Signatures are not a mandatory part of the software
Expand Down Expand Up @@ -905,11 +905,11 @@
A floating point number : ( ie, 1.25 is less than 1.3 )

value="multipartnumeric"
Numbers seperated by dots, where the numbers are interpreted as
Numbers separated by dots, where the numbers are interpreted as
integers (ie, 1.2.3 , 1.4.5.6 , 1.2.3.4.5.6.7 )

value="multipartnumeric+suffix"
Numbers seperated by dots, where the numbers are interpreted as
Numbers separated by dots, where the numbers are interpreted as
integers with an additional string suffix: (ie, 1.2.3a)

value="semver"
Expand Down
2 changes: 1 addition & 1 deletion cve_bin_tool/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def validate_spdx(filename):
"""
This function validates an SPDX file against the SPDX schema.
SPDX is a SBOM standard developed by the Linux Foundation. It is an XML or JSON schema that
describes the strcuture of an SPDX document.
describes the structure of an SPDX document.

Args:
filename (str): The path to the SPDX file to validate.
Expand Down
2 changes: 1 addition & 1 deletion cve_bin_tool/version_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def parse_version(version_string: str):

versionString = version_string.strip()

# convert all non alpha-numeric characters to be treated like . below
# convert all non alphanumeric characters to be treated like . below
# we could switch to a re split but it seems to leave blanks so this is less hassle
# Note: This expression may need improvement if we need to handle unicode
versionString = re.sub("[^0-9a-zA-Z]+", ".", versionString)
Expand Down
2 changes: 1 addition & 1 deletion cve_bin_tool/version_signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(self, table_name, mapping_function, duration) -> None:

@property
def dbname(self) -> str:
"""SQLite datebase file where the data is stored."""
"""SQLite database file where the data is stored."""
return str(Path(self.disk_location) / "version_map.db")

def open(self) -> None:
Expand Down
Empty file added screen,
Empty file.
Empty file added screen,green,creep,careen
Empty file.
Empty file added separate
Empty file.
Empty file added something
Empty file.
Empty file added the
Empty file.