drogon icon indicating copy to clipboard operation
drogon copied to clipboard

Assertion when executing SQL queries before app->run()

Open kotori2 opened this issue 3 years ago • 6 comments

Describe the bug Assertion error when descructor of orm::DbClient was called before app->run()

Assertion failed: idx < storage_.size(), file C:\vcpkg\buildtrees\drogon\src\v1.8.0-dfb5ab6251.clean\lib\inc\drogon/IOThreadStorage.h, line 100

To Reproduce

auto app = &drogon::app();
{
    auto a = drogon::orm::DbClient::newMysqlClient("host=127.0.0.1 port=3306 dbname=database user=user password=password", 1);
    a->execSqlSync("SHOW TABLES;");
}
app->addListener("0.0.0.0", 8080);
app->run();

Desktop (please complete the following information):

  • OS: Windows 11 with MSVC 19.33.31629.0
  • Browser: -
  • Version: 1.8.0 release via vcpkg

Additional context Add any other context about the problem here.

kotori2 avatar Sep 21 '22 04:09 kotori2

Also if you destruct DbClient right after initializing it, you will get another error:

D:\a\_work\1\s\src\vctools\crt\github\stl\src\mutex.cpp(64): mutex destroyed while busy

kotori2 avatar Sep 21 '22 04:09 kotori2

Also if you destruct DbClient right after initializing it, you will get another error:

D:\a\_work\1\s\src\vctools\crt\github\stl\src\mutex.cpp(64): mutex destroyed while busy

This one seems like triggered by:

  • DbClientImpl::init() called by drogon::orm::DbClient::newMysqlClient(...), inserted a connection create task into event loop
  • Destructor called immediately, but event loop was not stopped.
  • When event loop reached initialization point, it will crash because connectionsMutex_ was free.

Even if you add a loops_.wait() at the destructor function, it will still fail in DbClientImpl::newConnection because shared_from_this() can not get a proper this pointer. I have no idea how to fix this properly.

kotori2 avatar Sep 21 '22 06:09 kotori2

For the OG question I think it was caused by EventLoop not initialized in the current thread? Drogon's looping mechanism is pretty hard for me to understand tho

kotori2 avatar Sep 21 '22 07:09 kotori2

when you call a sync method of db client, it blocks current thread until the result returns, and you can't get the opportunity to call the run() function. There is deadlock in logic and you should avoid it.

an-tao avatar Sep 21 '22 07:09 an-tao

Okay I got it. It seems the main thread is depending on a EventLoop as well. When you are destructing the trantor::EventLoopThreadPool in DbClientImpl, the entire EventLoop in main thread will be wiped out. Here is a call stack: image

kotori2 avatar Sep 21 '22 07:09 kotori2

when you call a sync method of db client, it blocks current thread until the result returns, and you can't get the opportunity to call the run() function. There is deadlock in logic and you should avoid it.

Yea of course I know that. I'm doing some preperations (caching data into memory) before the application start, so I was intended to block the thread. BTW this method is actually working before (1.7.4 maybe?) so I think I'm doing something harmless here.

kotori2 avatar Sep 21 '22 07:09 kotori2