-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
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
use c-ares callback for socket close #3238
Conversation
lib/asyn-thread.c
Outdated
@@ -135,7 +135,7 @@ void Curl_resolver_cleanup(void *resolver) | |||
int Curl_resolver_duphandle(void **to, void *from) | |||
{ | |||
(void)from; | |||
return Curl_resolver_init(to); | |||
return Curl_resolver_init(NULL, to); |
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.
This looks wrong. Shouldn't this then pass in the new easy handle here? Otherwise this stores a NULL pointer to get used in the callback later on, and the callback doesn't deal with a NULL pointer...
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.
In case of asyn-thread.c Curl_resolver_duphandle is calling Curl_resolver_init that is not using the added easy parameter.
(By the way this is causing a new warning breaking travis check, so I'll submit a new patch to correct this.)
Reviewed this patch, I believe that I should add the new created easy as parameter to Curl_resolver_duphandle
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.
Ok, there is a problem for c-ares too.
In case Curl_resolver_duphandle
is called, ares_dup
is then called, but the sock_state_cb_data
of the new ares handle should be changed to point to the newly allocated easy.
Right now c-ares only supports setting the sock_state_cb_data
in init_by_options
so the only way that I see how to fix it now, is to create a new ares handle instead of using ares_dup
What do you think ?
8ca5075
to
79c2e15
Compare
When using c-ares for asyn dns, the dns socket fd was silently closed by c-ares without curl being aware. curl would then 'realize' the fd has been removed at next call of Curl_resolver_getsock, and only then notify the CURLMOPT_SOCKETFUNCTION to remove fd from its poll set with CURL_POLL_REMOVE. At this point the fd is already closed. By using ares socket state callback (ARES_OPT_SOCK_STATE_CB), this patch allows curl to be notified that the fd is not longer needed for neither for write nor read. At this point by calling Curl_multi_closed we are able to notify multi with CURL_POLL_REMOVE before the fd is actually closed by ares. In asyn-ares.c Curl_resolver_duphandle we can't use ares_dup anymore since it does not allow passing a different sock_state_cb_data
79c2e15
to
d30d8e1
Compare
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.
This change seems fine, just a little unfortunate that you bundle it with the c-ares fix since it gets less visibility then...
lib/asyn-ares.c
Outdated
Curl_multi_closed(easy->easy_conn, socket_fd); | ||
} | ||
else { | ||
DEBUGASSERT(easy->easy_conn); |
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 would suggest you either do the if() or the assert, not both. You either allow and expect NULLs to enter there, or not. Unless you have a reason to allow NULLs, I would prefer unconditional DEBUGASSERT there. I would also suggest a DEBUGASSERT(easy) to catch any such mistakes better.
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 definitely expect easy to be != NULL, so I could add a DEBUGASSERT(easy).
For easy->easy_conn, looking at the code I don't expect it to be NULL either, but I'm not familiar enough with the code to be 100% sure that it can't happen, do you prefer I keep the if or the assert ?
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.
Looking closer, it seems that easy_conn
might be NULL in some cases, if the socket for example gets closed before there's a connection setup.
But also, if that happens this code won't call Curl_multi_closed()
and thus the application won't be told about the closure, which seems wrong. I'm thinking Curl_multi_closed()
perhaps should also be modified ever so slightly to take a struct Curl_easy *data
as input argument instead of a connection. The actual function doesn't care about the connection and just wants the easy handle...
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 just pushed the change you suggested.
It seems that travis is still marked as "pending" when it's actually passed: https://travis-ci.org/curl/curl/builds/451829268 |
Thanks! |
When using c-ares for asyn dns, the dns socket fd was silently closed by c-ares without curl being aware. curl would then 'realize' the fd has been removed at next call of
Curl_resolver_getsock
, and only then notify theCURLMOPT_SOCKETFUNCTION
to remove fd from its poll set withCURL_POLL_REMOVE
. At this point the fd is already closed.Using the
ephiperfifo.c
example with the updated patch displayingepoll_ctl
errors allow reproducing the issue:Note that it only affect builds with ares enabled:
./configure --enable-ares --enable-debug