AsyncEngine
AsyncEngine copied to clipboard
libuv TCP considerations
From the IRC:
[15:16:32]is it possible for a TCP write req to fail (callback with error) while the connection remains alive? [15:17:04] ibc: well, yes that's possible in theory [15:17:09] although unlikely [15:17:16] in which cases? [15:17:49] ibc: hmm, when the os is very low on resources for example [15:18:22] ibc: but for all intents and purposes you should just assume that a socket is dead when uv_write() fails [15:18:41] so the callback error status says us that the data could not be sent, but the socket remains connected, am I right? If so, which ERRNO would UV generate in the write callback? [15:19:19] ibc: that's not defined. The errno is just whatever the actual error is that happened :-0 [15:19:30] yes, but in my case I always enable "receiving" so the way in which I expect to detect that the socket is dead is by receiving nread=-1 in read callback, hope this is right [15:20:10] ibc: yes, I think that's okay [15:20:31] thanks a lot [15:20:33] ibc: alternatively you could just cut the connection whenever the write fails [15:20:41] is that safe then? [15:21:02] ibc: so [15:21:02] if (status == -1) { [15:21:02] if (!uv_is_closing(handle)) uv_close(handle, close_cb); [15:21:02] } [15:21:11] oh I forgot "return" [15:21:30] if for example I try to send lot of data over a slow socket, couldn't the Kernel return error once its buffer is full or whatever? [15:21:31] ibc: the same would be in the recv callback although you should probably check the buf and free it if appropriate [15:21:50] ibc: yes the kernel could do that, but libuv normally handles that [15:21:57] ok [15:22:24] the typical error you would get is EAGAIN, and libuv will make sure to attempt to send it at a later point in time [15:22:31] (this is more or less the purpose of libuv in the first place) [15:22:51] about the recv callback, I assume that if I receive nread=-1 it means that data has NOT been received, so my read_alloc cb has not been called and I don't have to free the buf, am I wrong? [15:23:04] ibc: that's not correct [15:23:12] sure, I understand, and yes, I hope libuv does that for me :) [15:23:14] ibc: it *may* be called [15:23:58] ibc: in case your alloc cb was not called buf.base will be NULL and buf.len will be 0 [15:24:20] ibc: so you can just check that. [15:24:35] aja, good point! otherwise I should mantain some kind of state! [15:24:54] ibc: this behaviour is guaranteed [15:25:02] so you can just rely on it
NOTE: Check the same in UDP !
More stuf about TCP for receiving and disconnection:
[18:18:41]hi, easy question (I think there must be some bug in my code): [18:19:42] outbound TCP connection done and I call uv_close(handle), should the read cb be called with nread==-1 or not? [18:23:26] note: in my question I did start_read() [18:23:48] ibc: no. [18:23:55] ibc: uv_close will implicitly call read_stop [18:24:06] ibc: but in theory it may make the read callback once more with nread==0 [18:24:22] which might happen if it already called alloc_cb and wants you to give the buffer bacl [18:24:31] "it may" does not seem a very robust mechanism :) [18:24:40] aha, I understand [18:25:15] so if I call uv_close() in a connected socket, then I should call my "on_disconnection" callback by myself, am I right? [18:25:43] ibc: ehm... yes, if that's what you want to do :-) [18:25:53] clear, thanks a lot [18:26:07] ibc: normally you'll get -1/UV_EOF only if the remote gracefully closed the connection [19:11:02] hi, can I be sure that if I call uv_close() for a established connection, I won't be called to read cb with nread==-1 ? [19:11:43] I do know that it should not occur, I just want to be sure that it will never happen [19:14:42] ibc: should not happen.
Consider this also (found in a UV test unit):
if (req->handle->write_queue_size >= size * 2) {
break;
}