Lena Oxton
Lena Oxton

Reputation: 96

call uv_write from multi thread, its callback never get called

I've read the tcp-echo-server.c example from libuv, now I'm writing a small multi-thread tcp server based on that.

I used the uv_default_loop in the main thread to accept connections, and put new connection into a list.

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

and in the second thread, I broadcast a message to all connections I've got.

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

accepting connection works, reading from client works, but the writing part didn't work. no error code reported, but it's callback never got triggered.

I went through the doc, unable to find any clue yet. What did I miss?

by the way, I'm using std::thread, not the thread api from libuv.

Upvotes: 2

Views: 1622

Answers (1)

bertubezz
bertubezz

Reputation: 411

libuv is not thread safe thus you need to always access the loop from the same thread where it is running. If you want to push something from another thread you need to use uv_async_send function as follows.

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

Upvotes: 2

Related Questions