【问题标题】:call uv_write from multi thread, its callback never get called从多线程调用 uv_write,它的回调永远不会被调用
【发布时间】:2019-06-23 03:06:52
【问题描述】:

我已经阅读了 libuv 中的 tcp-echo-server.c 示例,现在我正在基于它编写一个小型多线程 tcp 服务器。

我在主线程中使用uv_default_loop 接受连接,并将新连接放入列表中。

// main thread
    uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr);

    uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0);
    int r = uv_listen((uv_stream_t*) &server, DEFAULT_BACKLOG, OnConnectionCallback);
    if (r)
    {
        ERROR("Listen error %s", uv_strerror(r));
        return;
    }
    uv_run(loop, UV_RUN_DEFAULT);

在第二个线程中,我向我拥有的所有连接广播了一条消息。

// second thread

    write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
    req->buf = uv_buf_init((char *)buffer->data(), buffer->size());
    int r = uv_write((uv_write_t*) req, (uv_stream_t *)this->uv, &req->buf, 1, write_callback);
    if (r)
    {
        ERROR("uv_write error: %s", uv_strerror(ret));
    }

接受连接有效,从客户端读取有效,但写入部分无效。没有报告错误代码,但它的回调从未被触发。

我浏览了文档,还没有找到任何线索。我错过了什么?

顺便说一句,我使用的是std::thread,而不是来自 libuv 的线程 api。

【问题讨论】:

  • libuv 除了uv_async 之外不是线程安全的。因此,您尝试做的事情是不安全的,并且会导致未定义的行为。
  • 那么如果ur_write api 不是线程安全的,那么在我的场景中最佳实践是什么?如果其他线程产生了一些要发送给客户端的数据,我是否应该将所有其他线程的数据交给主线程,然后由主线程执行实际发送?
  • 是的,您可以通过线程安全的数据结构将数据交给主线程uv_async 将其唤醒并发送到那里。

标签: multithreading libuv


【解决方案1】:

libuv 不是线程安全的,因此您需要始终从运行它的同一线程访问循环。如果你想从另一个线程推送一些东西,你需要使用uv_async_send函数,如下所示。

uv_loop_t loop;
uv_async_t async;
...
uv_async_init(loop, &async, [](uv_async_t* handle) {
  ...
  // call uv_write or any uv functions
});
uv_async_send(async);

【讨论】:

    猜你喜欢
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 2013-11-23
    • 2018-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多