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

prepare_stmt(sqlite3* db, std::string query) , the db parameter is nullptr #1361

Open
zhouniandi opened this issue Dec 11, 2024 · 3 comments

Comments

@zhouniandi
Copy link

zhouniandi commented Dec 11, 2024

in mutilthread read case, prepare_stmt(sqlite3* db, std::string query) function, the db parameter is nullptr
{4C36A2EC-13DE-4AB3-B9D8-6BD6F3F82CBE}

@fnc12
Copy link
Owner

fnc12 commented Dec 12, 2024

please provide the least code to reproduce this. Thanks

@zhouniandi
Copy link
Author

zhouniandi commented Dec 12, 2024

please provide the least code to reproduce this. Thanks

#include <iostream>
#include <boost/asio.hpp>
#include <sqlite_orm/sqlite_orm.h>
using namespace sqlite_orm;
using std::cout;
using std::endl;
using std::make_unique;
using std::string;
struct Employee {
    int id;
    std::string name;
    int age;
};

void run(boost::asio::io_context& context)
{
    boost::asio::io_context::work w(context);
    context.run();
}

void multithread_read_case()
{
    auto storage = make_storage("select.sqlite",
                            make_table("COMPANY",
                                make_column("ID", &Employee::id, primary_key()),
                                make_column("NAME", &Employee::name),
                                make_column("AGE", &Employee::age)));
    storage.sync_schema();
    storage.remove_all<Employee>();

    Employee paul{ -1, "Paul", 32 };
    Employee allen{ -1, "Allen", 25};
    Employee teddy{ -1, "Teddy", 23};
    Employee mark{ -1, "Mark", 25};
    Employee david{ -1, "David"};
    Employee kim{ -1, "Kim", 22};
    Employee james{ -1, "James", 24};

    paul.id = storage.insert(paul);
    allen.id = storage.insert(allen);
    teddy.id = storage.insert(teddy);
    mark.id = storage.insert(mark);
    david.id = storage.insert(david);
    kim.id = storage.insert(kim);
    james.id = storage.insert(james);

    std::vector<boost::asio::io_context> contexts(10);
    std::vector<std::thread> threads;
    for(auto& context : contexts)
    {
        threads.emplace_back(std::bind(run, std::ref(context)));
    }
    for (std::size_t index = 0; index < 10000000; index++)
    {
        auto pos = index % contexts.size();
        boost::asio::post(contexts[pos], [&]() {
            try
            {
                storage.select(sqlite_orm::columns(&Employee::id, &Employee::name));
            }
            catch (std::system_error& e)
            {
                std::cout << e.what() << std::endl;
            }
        });
    }
    for (auto& thread : threads)
    {
        if (thread.joinable())
        {
            thread.join();
        }
    }
}

int main(int argc, char** argv)
{
#if defined(_WIN32) || defined(_WIN64)
    SetConsoleOutputCP(65001);
#endif
    multithread_read_case();
    return 0;
}

{30B68760-A03C-4E44-A180-A0C3D06E4DFD}

The error is more likely to occur in the Release version.

@zhouniandi
Copy link
Author

zhouniandi commented Dec 19, 2024

please provide the least code to reproduce this. Thanks

 struct connection_holder {

                connection_holder(std::string filename_) : filename(std::move(filename_)) {}

                void retain() {
                    std::lock_guard<std::mutex> lock(_mutex);
                    if(1 == ++this->_retain_count) {
                        auto rc = sqlite3_open(this->filename.c_str(), &this->db);
                        if(rc != SQLITE_OK) {
                            throw_translated_sqlite_error(db);
                        }
                    }
                }

                void release() {
                    std::lock_guard<std::mutex> lock(_mutex);
                    if(0 == --this->_retain_count) {
                        auto rc = sqlite3_close(this->db);
                        if(rc != SQLITE_OK) {
                            throw_translated_sqlite_error(db);
                        }
                    }
                }

                sqlite3* get() const {
                    return this->db;
                }

                int retain_count() const {
                    return this->_retain_count;
                }

                const std::string filename;

              protected:
                std::mutex _mutex;
                sqlite3* db = nullptr;
                int _retain_count{};
            };

add mutex can resolve this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants