Socket callbacks during curl_multi_cleanup()

Dimitry Andric via curl-library <[email protected]>
Newsgroups gmane.comp.web.curl.library
Message-ID <[email protected]>
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
@@ -181,6 +181,8 @@ 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:
@@ -240,7 +242,9 @@ 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.html
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.