在libev事件回调函数中调用阻塞函数会阻塞整个应用吗?

时间:2017-03-09 07:29:41

标签: c event-driven mysql-connect libev

我使用libev来开发我的事件驱动的应用程序。我喜欢在事件中查询远程mysql服务器。所以, mysql_real_connect 阻止整个应用程序或 my_read_cb

根据以下代码

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);

1 个答案:

答案 0 :(得分:2)

它会阻止整个应用程序,因为回调函数my_read_cb()在与ev_run()函数相同的(也就是主要的)线程中执行。 这就是reactor pattern的工作原理,您的代码应该是"非阻塞"这意味着你应该避免任何I / O等待,sleep()调用,互斥等待等。在你的情况下很难用来自各种库(如MySQL驱动程序)的传统阻塞代码来遵循这样的要求。

至少有三种解决方法:

  • 接受事件循环不时被阻止的事实。在某些应用中,这可能不是什么大问题。
  • 实现proactor pattern - 这基本上意味着每个处理程序回调都在不同于主线程的工作线程中执行,因此,事件循环不会被阻止。这就是Node.js提供的内容,或者是C world libuv等等。
  • 查找与事件循环兼容的库的异步/非阻塞实现。你需要在这里特别幸运。一个例子是例如https://c-ares.haxx.se用于异步DNS解析(与getaddrinfo系列中的POSIX系统DNS阻止呼叫相反)。