Search code examples
cevent-drivenmysql-connectlibev

Does calling a blocking function inside libev event callback function blocks whole app?


I use libev to develope my event-driven app. I like to query remote mysql server inside events. so, Do mysql_real_connect block whole application or just my_read_cb

according to following code

my_read_cb(EV_P_ ev_io *w, int revents) {

    mysql_real_connect(*mysql, "host", "user", "pass", "db", 3306, NULL, 0);
}


struct ev_loop *loop = ev_default_loop(0);
ev_io_init(io, my_read_cb, network_fd, EV_READ);
ev_io_start(loop, io);
ev_run(loop, 0);

Solution

  • It blocks the whole application because the callback function my_read_cb() is executed in the same (aka main) thread as ev_run() function. This is how reactor pattern works, your code should be "non-blocking" which means that you should avoid any I/O waits, sleep() calls, mutex waits etc. It is difficult to follow such a requirement with traditional blocking code from various libraries such as MySQL driver in your case.

    There are (at least) three ways how to solve it:

    • Accept the fact that event loop is blocked time-to-time. It may not be a such a big deal in some apps.
    • Implement proactor pattern - that basically means that each handler callback is executed in a worker thread different from a main thread and for that reason, the event loop is not blocked. This is what Node.js provides or in C world libuv and so on.
    • Find an asynchronous/non-blocking implementation of the library compatible with your event loop. You need to be particularly lucky here. An example is e.g. https://c-ares.haxx.se for async DNS resolving (in contrast to POSIX system DNS blocking calls in getaddrinfo family).