Reputation: 231
I'm testing a simple server architecture I've developed using libuv. Every time the server recieves something from a client, it splits the body by '\r' and broadcasts to all observers, each message.
Then, the observer I'm using to test, calls the server->write() method with the same origin message (echo server).
The problem is, every time I run the program it randomly works or doesn't.
When it doesn't work, the error message is:
Assertion failed: (req->write_index < req->nbufs), function uv__write, file src/unix/stream.c, line 869.
Abort trap: 6
Full code is here: https://github.com/ghostec/film
Most of the code is in this file: https://github.com/ghostec/film/blob/master/server/server.cpp
Edit: Apparently this has something to do with the fact that calls to uv_write are being made inside a uv_queue_work. Since they are all writing to the same handler, if they are out of order when invoked inside libuv loop, something bad happens. I'm not sure if my assessment is right, however.
Upvotes: 1
Views: 1131
Reputation: 50550
As mentioned in the documentation of uv_write
:
Note The memory pointed to by the buffers must remain valid until the callback gets called. This also holds for uv_write2().
On the other side, this is your code:
void Server::write(Message message) {
uv_write_t req;
uv_buf_t* buf = new uv_buf_t();
buf->base = &(std::vector<char>(message.data.begin(), message.data.end()))[0];
buf->len = message.data.size();
uv_write(&req, message.handle, buf, 1, [](uv_write_t* req, int status) -> void {});
delete buf;
}
In particular, this line of code smells:
buf->base = &(std::vector<char>(message.data.begin(), message.data.end()))[0];
Note also that the same applies for the uv_buf
, therefore deleting it before the callback gets called smells as well. More than suspecting libuv fails internally, I'd say you should be grateful for it performs really well and you don't see the problem at each use of uv_write
even if you are not true to the requirements of the library.
For you tagged the questions with c++
, I'd suggest you to use one of the existing wrappers that correctly manage memory and data structures for you under the hood. See section bindings in the link above.
Upvotes: 1