Buy commercial curl support. We
help you work out your issues, debug your libcurl applications, use the API,
port to new platforms, add new features and more. With a team lead by the
curl founder Daniel himself.
Socket callbacks during curl_multi_cleanup()
- Contemporary messages sorted: [ by date ] [ by thread ] [ by subject ] [ by author ] [ by messages with attachments ]
From: Dimitry Andric via curl-library <curl-library_at_lists.haxx.se>
Date: Sat, 22 Feb 2025 17:50:04 +0100
After https://github.com/curl/curl/commit/a58b50f ("transfer:
Curl_sendrecv() and event related improvements") for issue #14561,
socket callbacks can be triggered during curl_multi_cleanup() calls.
In our project that uses curl_multi, we noticed this because our socket
callback function attempted to manipulate some members of a C++ class
that wraps curl_multi. Because that particular object was being
destructed, this resulted in trouble. (Pure virtual functions being
called, and/or annoying segfaults.)
We have now worked around this by calling curl_multi_setopt(multi,
CURLMOPT_SOCKETFUNCTION, NULL) just before calling curl_multi_cleanup(),
but we are wondering if this new behavior is as expected?
It is easy to demonstrate the behavior, by changing the standard
multi-event example from the documentation, as follows:
diff --git a/docs/examples/multi-event.c b/docs/examples/multi-event.c
index 450ac7871..78a56a26d 100644
--- a/docs/examples/multi-event.c
+++ b/docs/examples/multi-event.c
_at__at_ -181,6 +181,8 _at__at_ static int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp,
(void)easy;
(void)userp;
+ fprintf(stderr, "handle_socket: easy=%p, s=%d, action=%d\n", easy, s, action);
+
switch(action) {
case CURL_POLL_IN:
case CURL_POLL_OUT:
_at__at_ -240,7 +242,9 _at__at_ int main(int argc, char **argv)
event_base_dispatch(base);
+ fprintf(stderr, "calling curl_multi_cleanup\n");
curl_multi_cleanup(curl_handle);
+ fprintf(stderr, "called curl_multi_cleanup\n");
event_free(timeout);
event_base_free(base);
If you build this modified multi-event example, and link it against
curl-8_9_1-236-g432f2fd9a (so just before the a58b50f commit), the
output looks something like:
$ ./multi-event-curl-8_9_1-236-g432f2fd9a https://curl.se/
Added download https://curl.se/ -> 1.download
handle_socket: easy=0x5586918cd7a0, s=9, action=1
handle_socket: easy=0x5586918cd7a0, s=9, action=4
handle_socket: easy=0x5586918cd7a0, s=9, action=2
handle_socket: easy=0x5586918cd7a0, s=9, action=1
handle_socket: easy=0x5586918cd7a0, s=9, action=4
https://curl.se/ DONE
calling curl_multi_cleanup
called curl_multi_cleanup
But link it against curl-8_9_1-237-ga58b50fca (or later!), and the
output becomes:
$ ./multi-event-curl-8_9_1-237-ga58b50fca https://curl.se/
Added download https://curl.se/ -> 1.download
handle_socket: easy=0x55fa15be87a0, s=9, action=1
handle_socket: easy=0x55fa15be87a0, s=9, action=4
handle_socket: easy=0x55fa15be87a0, s=9, action=2
handle_socket: easy=0x55fa15be87a0, s=9, action=1
handle_socket: easy=0x55fa15be87a0, s=9, action=4
https://curl.se/ DONE
calling curl_multi_cleanup
handle_socket: easy=0x55fa15be72e0, s=9, action=1
handle_socket: easy=0x55fa15be72e0, s=9, action=4
called curl_multi_cleanup
You can see that handle_socket() is now being called _during_ the
curl_multi_cleanup() call, whereas that did not happen before.
As far as we can determine, these callbacks occur because a58b50fca
introduces an extra internal handle in conncache.c, which gets triggered
with a CURL_POLL_IN event, followed by a CURL_POLL_REMOVE.
The question is whether that was intentional or not?
-Dimitry
Date: Sat, 22 Feb 2025 17:50:04 +0100
After https://github.com/curl/curl/commit/a58b50f ("transfer:
Curl_sendrecv() and event related improvements") for issue #14561,
socket callbacks can be triggered during curl_multi_cleanup() calls.
In our project that uses curl_multi, we noticed this because our socket
callback function attempted to manipulate some members of a C++ class
that wraps curl_multi. Because that particular object was being
destructed, this resulted in trouble. (Pure virtual functions being
called, and/or annoying segfaults.)
We have now worked around this by calling curl_multi_setopt(multi,
CURLMOPT_SOCKETFUNCTION, NULL) just before calling curl_multi_cleanup(),
but we are wondering if this new behavior is as expected?
It is easy to demonstrate the behavior, by changing the standard
multi-event example from the documentation, as follows:
diff --git a/docs/examples/multi-event.c b/docs/examples/multi-event.c
index 450ac7871..78a56a26d 100644
--- a/docs/examples/multi-event.c
+++ b/docs/examples/multi-event.c
_at__at_ -181,6 +181,8 _at__at_ static int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp,
(void)easy;
(void)userp;
+ fprintf(stderr, "handle_socket: easy=%p, s=%d, action=%d\n", easy, s, action);
+
switch(action) {
case CURL_POLL_IN:
case CURL_POLL_OUT:
_at__at_ -240,7 +242,9 _at__at_ int main(int argc, char **argv)
event_base_dispatch(base);
+ fprintf(stderr, "calling curl_multi_cleanup\n");
curl_multi_cleanup(curl_handle);
+ fprintf(stderr, "called curl_multi_cleanup\n");
event_free(timeout);
event_base_free(base);
If you build this modified multi-event example, and link it against
curl-8_9_1-236-g432f2fd9a (so just before the a58b50f commit), the
output looks something like:
$ ./multi-event-curl-8_9_1-236-g432f2fd9a https://curl.se/
Added download https://curl.se/ -> 1.download
handle_socket: easy=0x5586918cd7a0, s=9, action=1
handle_socket: easy=0x5586918cd7a0, s=9, action=4
handle_socket: easy=0x5586918cd7a0, s=9, action=2
handle_socket: easy=0x5586918cd7a0, s=9, action=1
handle_socket: easy=0x5586918cd7a0, s=9, action=4
https://curl.se/ DONE
calling curl_multi_cleanup
called curl_multi_cleanup
But link it against curl-8_9_1-237-ga58b50fca (or later!), and the
output becomes:
$ ./multi-event-curl-8_9_1-237-ga58b50fca https://curl.se/
Added download https://curl.se/ -> 1.download
handle_socket: easy=0x55fa15be87a0, s=9, action=1
handle_socket: easy=0x55fa15be87a0, s=9, action=4
handle_socket: easy=0x55fa15be87a0, s=9, action=2
handle_socket: easy=0x55fa15be87a0, s=9, action=1
handle_socket: easy=0x55fa15be87a0, s=9, action=4
https://curl.se/ DONE
calling curl_multi_cleanup
handle_socket: easy=0x55fa15be72e0, s=9, action=1
handle_socket: easy=0x55fa15be72e0, s=9, action=4
called curl_multi_cleanup
You can see that handle_socket() is now being called _during_ the
curl_multi_cleanup() call, whereas that did not happen before.
As far as we can determine, these callbacks occur because a58b50fca
introduces an extra internal handle in conncache.c, which gets triggered
with a CURL_POLL_IN event, followed by a CURL_POLL_REMOVE.
The question is whether that was intentional or not?
-Dimitry
-- Unsubscribe: https://lists.haxx.se/mailman/listinfo/curl-library Etiquette: https://curl.se/mail/etiquette.htmlReceived on 2025-02-22