SQLite Forum

App using SQlite C API faces segmentation fault
Login
Hello,

I've an application writing log data to a SQLite3 database. Randomly, reason why I'm not able to reproduce the issue when needed, I'm facing app crash with segmentation fault. I succeeded to generate a SEGV dump which shows the following 2 traces.

I posting this as I'm trying to figure out what is the root cause for weeks but still struggling to solve. 

# 1) sqlite3ExprListDup Trace
> `ip 0x7fff797b5b5d: _sigtramp+0x1d
ip 0x7fff787b11d7: sqlite3ExprListDup+0x127
ip 0x7fff787b5e62: sqlite3SelectDup+0x132
ip 0x7fff787848af: selectExpander+0x4df
ip 0x7fff787842f1: sqlite3WalkSelect+0x31
ip 0x7fff7885a87a: sqlite3SelectPrep+0x8a
ip 0x7fff7877a7be: sqlite3Select+0x28e
ip 0x7fff7874e28a: yy_reduce+0x10ca
ip 0x7fff7874b658: sqlite3RunParser+0x218
ip 0x7fff78749d0a: sqlite3LockAndPrepare+0x48a
ip 0x7fff787d61e7: sqlite3_prepare_v2+0xf7
ip 0x10ac75422: Connector::sqlite3Driver::executeDQL(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)+0x82`

# 2) sqlite3WhereBegin Trace
> `ip 0x7fff69eb5b5d: _sigtramp+0x1d
ip 0x7fff68e8b804: sqlite3WhereBegin+0x1424
ip 0x7fff68e7da0f: sqlite3Select+0x34df
ip 0x7fff68f6010f: multiSelectOrderBy+0xcef
ip 0x7fff68e7d24e: sqlite3Select+0x2d1e
ip 0x7fff68e7caaa: sqlite3Select+0x257a
ip 0x7fff68e4e28a: yy_reduce+0x10ca
ip 0x7fff68e4b658: sqlite3RunParser+0x218
ip 0x7fff68e49d0a: sqlite3LockAndPrepare+0x48a
ip 0x7fff68ed61e7: sqlite3_prepare_v2+0xf7
ip 0x100996432: Connector::sqlite3Driver::executeDQL(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)+0x82`

The ***first trace*** occurs on **INSERT** statements into table that contains 6 columns. I found on the Web similar cases (Firefox) resulting from a bug prior to SQlite version 3.18.x and that was corrected as from this version.
The ***second trace*** occurs on **SELECT** statement from the same table.

The environment is C++11 on MacOSX with sqlite-3.22.0 C API.

The log database is a one table structure.
# Table DDL
> `CREATE TABLE IF NOT EXISTS log (uuid TEXT NOT NULL
                                sourcename TEXT NOT NULL,
                                sourceipaddress TEXT NOT NULL,
                                stimestamp TEXT NOT NULL,
                                qtimestamp TEXT NOT NULL,
                                severity INTEGER NOT NULL,
                                content TEXT NOT NULL);
CREATE INDEX IF NOT EXISTS idx_uuid ON log (uuid);
CREATE INDEX IF NOT EXISTS idx_stimestamp ON log (stimestamp);
CREATE INDEX IF NOT EXISTS idx_qtimestamp ON log (qtimestamp);
CREATE INDEX IF NOT EXISTS idx_severity ON log (severity);`

When inserting data into the log table, the app executes **INSERT** statements by lot (50 rows) using a wrapper and ensures **TRANSACTION BEGIN** and **COMMIT/ROLLBACK**.
# Application source code extract
> `[public] const bool Connector::open(const std::string& dbName, sqlite3 *dbConnection) {
    int      connStatus   = sqlite3_open("log.db", &dbConnection);
    if (connStatus == SQLITE_OK) {
        return true;
        ... //Wrapper maintains the connection to the SQLite database
    }
    else {
        return false;
    }
}
[public] const bool Connector::startTransac() {
    ...
}
[public] const bool Connector::commitTransac() {
    ...
}
[public] const bool Connector::rollbackTransac() {
    ...
}
[public] const int Connector::executeDQL(const std::string& queryStmt) {
    if (queryStmt.find("SELECT ") >= 0) {
        sqlite3_stmt    *statement    = nullptr;
        int              sqLiteResult = sqlite3_prepare_v2(dbConnection, queryStmt.c_str(), -1, &statement, NULL);
        if (sqLiteResult == SQLITE_OK) {
            sqLiteResult = sqlite3_step(statement);
            sqLiteResult = sqlite3_finalize(statement);
        }
        return sqLiteResult;
    }
    else {
        return this->executeDML(queryStmt);
    }
}
[public] const int Connector::executeDML(const std::string& queryStmt) {
    char    *errorMsg = 0;
    int      sqLiteResult = sqlite3_exec(dbConnection, queryStmt.c_str(), nullptr, nullptr, &_errorMessage);
    if (sqLiteResult == SQLITE_OK) {
        sqLiteResult = sqlite3_changes(dbConnection);
    }
    return sqLiteResult
}`

The application is _multi-threaded_ with mutex lockers but the connector class is a _singleton_ not allowing concurrent calls.

Any help or suggestion to solve my issue would so much appreciated.