-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
multi: add curl_multi_wakeup() #4608
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Why do we need |
|
If it is enabled then every multi uses two additional fds and the initialization time will be a bit slower. If someone never uses unblock, these are really unnecessary. Secondly, because Curl_socketpair can fail (mostly on Windows), we'd like to know before calling curl_multi_poll() whether this unblock feature will work, so we can adjust the timeout based on that. |
|
My second reason in the previous reply is really weak: we can simply call curl_multi_unblock() and see if it succeeda before the first poll to adjuat timeouts. |
|
On second thought, this perf penalty doesn't seem that huge considering every DNS lookup will also create a socketpair when using the threaded resolver. I'll update this PR to have it enabled automatically. Also it'd be easier to not include a new error code, but I couldn't find any that looked good. Should I reuse one of the existing codes and if so then which one? |
|
I've removed the setopt option, now it is enabled if USE_SOCKETPAIR is defined and USE_BLOCKING_SOCKETS is not (blocking write socket can cause a deadlock if unblock is called from the same thread that will call poll). Idea: After this is merged probably the threaded resolver can be refactored to call unblock after it is done instead of creating a new socketpair every time. |
Two ideas:
Yes and once we have the docs and tests worked out, that should be really easy! |
|
Thanks for the quick feedback! I'll try to address the implementation and docs issues today, and I'll try to add tests after that. |
|
I have another question: |
|
Ah, good thinking - I hadn't considered that subtlety! Yes, I would be fine with making it only work for |
aeb5ce0 to
2251546
Compare
|
I've updated the implementation and docs, and also added the first test which tests unblocks and poll from a single thread without any easy handles attached. I'll add more tests (including a multi-threaded one) and an example later.
|
9b2da0a to
6ff353a
Compare
include/curl/multi.h
Outdated
| /* | ||
| * Name: curl_multi_unblock() | ||
| * | ||
| * Desc: unblocks a "hanging" curl_multi_poll call. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might improve the description, as unblocks a "hanging" curl_multi_poll call. - sounds like a call that hung (eg deadlocked).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "unblock" word itself can sound a bit horrifying I chose this because it was already in the TODO sectiom, personally I'd prefer to call this "wakeup". The description then could be something like " wakes up a sleeping curl_multi_poll call". Ideas? Or if we leave it named unblock, what description should we use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming is hard. I don't have any problems with renaming it *_wakeup if you think that's better.
Is there any previous art somewhere for a similar API that we could copy the name from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was mainly referring to "hanging" in the description. not the _unblock part. Description perhaps should make it clear that the api unblocks/wake up another thread that's blocked on/waiting for curl_multi_poll calls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now it is called curl_multi_wakeup and the short description says wakes up a sleeping curl_multi_poll call, I hope this is better.
lib/multi.c
Outdated
| @@ -367,6 +368,21 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ | |||
|
|
|||
| /* -1 means it not set by user, use the default value */ | |||
| multi->maxconnects = -1; | |||
|
|
|||
| #ifdef ENABLE_UNBLOCK | |||
| if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->unblock_pair) < 0) { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- wouldn't that be confusing to have AF_UNIX even on windows? (I know that it's ignored inside Curl_socketpair)
- why sock_stream? udp should to be lighter than tcp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldn't that be confusing to have AF_UNIX even on windows? (I know that it's ignored inside Curl_socketpair)
Won't it be equally confusing to setup an #ifdef for the value when it isn't even used on that platform?
why sock_stream? udp should to be lighter than tcp
Well, we want the pipe to be a reliable stream. I'm not sure what to expect from this if we use datagrams instead... besides, does it really matter (can the "overhead" even be measured?) for this simple use case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chose these parameters because this is how it is already used in the threaded resolver. These can be later improved in both places in a separate PR. Based on https://stackoverflow.com/questions/13953912/difference-between-unix-domain-stream-and-datagram-sockets I think SOCK_STREAM is better here because if we always send 1-byte messages then we would only be able to read a single byte at a time with SOCK_DGRAM (Note: I didn't test if this is really the case)
The number just have to be unique, the grouping or ranges are only for humans so you can go however you think is fine. 1564 looks perfect to me!
If we can't provide any other hints to help figure that out in the test, I guess we need to test with something and see what works... |
68a865f to
85f590f
Compare
|
The latest CI run shows it seems to work everywhere except on Windows when compiled with MSYS. In that case, the tests can fail at I have currently no access to a Windows machine with MSYS, so I'll add some debug logging of error codes inside curl and let appveyor build that. |
f847531 to
e5f088a
Compare
|
Strange, based on these debug messages it seems that writing to these socket is much more asynchronous than it is on any other platform, meaning that if we write to this socket then later on that same thread it's possible the data is not even ready to be read. |
54575e5 to
2710e15
Compare
f6262b7 to
c553574
Compare
This commit adds curl_multi_wakeup() which was previously in the TODO list under the curl_multi_unblock name. On some platforms and with some configurations this feature might not be available or can fail, in these cases a new error code (CURLM_WAKEUP_FAILURE) is returned from curl_multi_wakeup(). Fixes curl#4418
|
I think I'm ready with this PR, please review. In the last CI run all failures seemed to be unrelated to this change. I've started another one just to make sure. Notable changes since initial version:
|
This commit adds curl_multi_wakeup() which was previously in the TODO
list under the curl_multi_unblock name.
On some platforms and with some configurations this feature might not be
available or can fail, in these cases a new error code
(CURLM_WAKEUP_FAILURE) is returned from curl_multi_wakeup()
Fixes #4418
This PR is a work-in-progress, I'm submitting it to receive feedback about
the design choices and the implementation.
I've tested it using our application on Windows, Linux, macOS and Android
platforms, and it seems to work well.
I'm not sure how to add a test case for this in the curl test suite, do you have
an idea? Or probably some example should be added as well.