Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Make uv_udp_send send data immediately if possible #1358

Merged
merged 2 commits into from
Jul 8, 2014
Merged

Make uv_udp_send send data immediately if possible #1358

merged 2 commits into from
Jul 8, 2014

Conversation

saghul
Copy link
Contributor

@saghul saghul commented Jul 5, 2014

Please review with care.

/cc @indutny @txdv @ibc

@@ -422,8 +401,15 @@ int uv__udp_send(uv_udp_send_t* req,
if (err)
return err;

uv__req_init(handle->loop, req, UV_UDP_SEND);
/* It's legal for write_queue_size > 0 even when the write_queue is empty;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean send_queue_size.

@ibc
Copy link
Contributor

ibc commented Jul 5, 2014

Please yes. UDP is important, really. Not so much as TCP (and its loved HTTP which dominates the world and will replace "Internet") but, somehow, UDP may be important.

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

Thanks for the comments, @ibc. I wanted to put it up for review quickly in case you guys had some spare cycles to review the code.

Now, this patchset includes some required minor changes to how UDP handles operate internally, which actually make them a bit more similar to how streams behave:

  • When @txdv introduced the send_queue_size/count, it was decreased the moment sendmsg happened. It's now deferred until the request is popped out of the completed queue, right before the callback is called. The reson for this is that if you call uv_udp_send and the send completes immediately, uv_try_send would also try to send a datagram, and succeed, before the send callback from the previous send request was ever called, thus creating some inconsistent situations. Moreover, it's important not to decrease the byte count in case of error, because the user could think that the write completed ok (before getting the callback) because the size is 0, and continue attempting to write on a dead UDP handle. (this is also the case for streams, btw).

An interesting note: the change I had to make in test-watcher-cross-stop ilustrates the usefulness of this patch. On Linux, all send requests are completed immediately, on that test.

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

Please yes. UDP is important, really. Not so much as TCP (and its loved HTTP which dominates the world and will replace "Internet") but, somehow, UDP may be important.

Nobody said otherwise. Features are developed if/when there is need, curiosity, interest or patches, but there is only so much time. Discussions and patches like what @txdv you and I have done for try_send really motivate me to improve UDP, so here we are :-)

@txdv
Copy link
Contributor

txdv commented Jul 6, 2014

I'm reviewing wait a bit.

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

I'm reviewing wait a bit.

Thanks! No rush, we are not in a hurry.

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

@txdv force pushed. Now all the requests that will never complete are added to que completed queue and run in order. This actually makes the code more concise, as there is a single place where the completed queue is processed, req-> status will have the correct value (ECANCELLED), and I added a couple of asserts about queue_size/count, since they should be 0 after all callbacks have been run.

@txdv
Copy link
Contributor

txdv commented Jul 6, 2014

More delitions than additions and a feature more.

One central place to call the the send_cb makes it more concise, yes.

One question though, why are we calling the send_cb on success with 0 though?

https://github.com/saghul/libuv/blob/a29ea0fd5f34c9e8ebfd51a2363e57ff6ffb3f38/src/unix/udp.c#L112-L114

Don't we want to pass the amount we have written?

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

Don't we want to pass the amount we have written?

I didn't change that. I guess the reason is that in UDP you either send the whole datagram or you don't. But we could get rid of the if and always return req->status, which has the number of bytes written.

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

5 tests are failing

Hum, I cannot reproduce that on my Linux machine. I'll go through the code and test it on OSX as well a bit later.

@txdv
Copy link
Contributor

txdv commented Jul 6, 2014

@saghul It was my changed that made it fail, It is not failing.

Node used to return the buffer.length (which was faulty, because we could send less).

nodejs/node-v0.x-archive@a382c9a97 look at dgram.js

Now it returns the sent size. Maybe we should get rid of the if in libuv and just pass status.

It would be 'consistent' with the write function I guess? Do stream_write cbs get a callback with 0 or the size of what they have written?

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

@txdv they get 0, because the callback is not called until all data has been sent. So it's already consistent. I could update the comment, though.

@txdv
Copy link
Contributor

txdv commented Jul 6, 2014

Does the uv_write_cb in uv_write get called with 0 as well?

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

Does the uv_write_cb in uv_write get called with 0 as well?

Yes.

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

@indutny, this one is ready to land IMHO, can you PTAL?

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

I already merged the last patch I had in this set (377bf68). It was unrelated and almost all UDP tests were failing on Windows without it.

@txdv
Copy link
Contributor

txdv commented Jul 6, 2014

yes, my mistake, should have been in my commit

@saghul
Copy link
Contributor Author

saghul commented Jul 6, 2014

No problem!

@saghul
Copy link
Contributor Author

saghul commented Jul 7, 2014

@indutny, any further comments?

It's possible that recv_cb_called is bigger than the number of sockets,
because if all sends succeed the recv callback is called twice: once
with the actual data, and another time with 0.
@saghul saghul merged commit ad78e45 into joyent:master Jul 8, 2014
@saghul
Copy link
Contributor Author

saghul commented Jul 8, 2014

Thanks guys, landed!

@saghul saghul deleted the udp-send-immediate branch September 11, 2014 19:52
yosuke-furukawa added a commit to nodejs/node that referenced this pull request May 10, 2015
dgram#send callback was changed synchronously.
The PR-URL is here joyent/libuv#1358

This commit is temporary fix until libuv issue is resolved.
libuv/libuv#301

PR-URL: #1313
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Trevor Norris <[email protected]>
Fishrock123 pushed a commit to Fishrock123/node that referenced this pull request May 19, 2015
dgram#send callback was changed synchronously.
The PR-URL is here joyent/libuv#1358

This commit is temporary fix until libuv issue is resolved.
libuv/libuv#301

PR-URL: nodejs#1313
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Trevor Norris <[email protected]>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants