yesodweb / yesod

A RESTful Haskell web framework built on WAI.
http://www.yesodweb.com/
MIT License
2.63k stars 369 forks source link

Unix: do not use bound threads when using MySQL/MariaDB #1483

Open DemiMarie opened 6 years ago

DemiMarie commented 6 years ago

It is possible to solve the initialization problems when using the MariaDB/MySQL client drivers by using a single C++ source file and C++ thread_local objects:

C++:


namespace {

class MariaDBThreadInitializer {
public:
    MariaDBThreadInitializer() {
        mysql_thread_init();
    }
    ~MariaDBThreadInitializer() {
        mysql_thread_end();
    }
};

}

extern "C" void MariaDB_Init() {
    thread_local MariaDBThreadInitializer;
}

Each Connector/C C function is wrapped in another C or C++ function that calls MariaDB_Init() first. The wrapper is called from Haskell.

On Linux with glibc and libstdc++, this works because:

We can also do this in pure C, by abusing __cxa_thread_atexit_impl, an undocumented function from the GNU C Library that is meant to be only called by the C++ runtime.

On Windows, this doesn’t work reliably, because the destructors are called from DllMain which could fire after the MariaDB client library has already been unloaded. However, Windows doesn’t have high performance anyway, so this shouldn’t affect production uses.

MaxGabriel commented 6 years ago

I'm not familiar with the MySQL/MariaDB initialization problems you're referencing, but should this be reported to a lower-level package? Maybe https://github.com/paul-rouse/mysql ?

paul-rouse commented 6 years ago

Sorry I'm a little late. I am not an expert on C++, so I am not 100% certain how this interacts with Haskell threads. Also, does it add any any significant overhead on each call checking whether the thread needs initialisation? The alternative in a Yesod site - using bound threads - also has some additional overhead, so it might not matter.

That said, when I get a bit of spare time, I intend to try out mysql-haskell via persistent-mysql-haskell. It completely avoids the problem by implementing the protocol in Haskell instead of using the standard client library, and think it is probably the way to go in the long run.