curl / Mailing Lists / curl-library / Single Mail
Buy commercial curl support from WolfSSL. 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 himself.

[PATCH] asyn-thread: issue CURL_POLL_REMOVE before closing socket

From: Eric Wong via curl-library <curl-library_at_cool.haxx.se>
Date: Sat, 10 Aug 2019 22:19:06 +0000

This avoids EBADF errors from EPOLL_CTL_DEL operations in the
ephiperfifo.c example. EBADF is dangerous in multi-threaded
applications where I rely on epoll_ctl to operate on the same
epoll description from different threads.

---
  If you prefer to pull:
  The following changes since commit afce0620a29a98989f09f3cc4534534df5f74764:
    ngtcp2: make the QUIC handshake work (2019-08-10 16:07:33 +0200)
  are available in the Git repository at:
    https://80x24.org/curl.git socketpair-remove
  for you to fetch changes up to 9a1f2f54b0348646e961a0e043de9fda49f235ca:
    asyn-thread: issue CURL_POLL_REMOVE before closing socket (2019-08-10 22:15:45 +0000)
  ----------------------------------------------------------------
  Eric Wong (1):
        asyn-thread: issue CURL_POLL_REMOVE before closing socket
 lib/asyn-thread.c | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 222e78d98..24da74885 100755
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -164,6 +164,7 @@ struct thread_sync_data {
                             duplicate */
   int port;
 #ifdef HAVE_SOCKETPAIR
+  struct connectdata *conn;
   curl_socket_t sock_pair[2]; /* socket pair */
 #endif
   int sock_error;
@@ -201,11 +202,10 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
     Curl_freeaddrinfo(tsd->res);
 
 #ifdef HAVE_SOCKETPAIR
-  /* close socket pair */
-  if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
-    sclose(tsd->sock_pair[0]);
-  }
-
+  /*
+   * close one end of the socket pair (may be done in resolver thread);
+   * the other end (for reading) is always closed in the parent thread.
+   */
   if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
     sclose(tsd->sock_pair[1]);
   }
@@ -382,6 +382,10 @@ static void destroy_async_data(struct Curl_async *async)
   if(async->os_specific) {
     struct thread_data *td = (struct thread_data*) async->os_specific;
     int done;
+#ifdef HAVE_SOCKETPAIR
+    curl_socket_t sock_rd = td->tsd.sock_pair[0];
+    struct connectdata *conn = td->tsd.conn;
+#endif
 
     /*
      * if the thread is still blocking in the resolve syscall, detach it and
@@ -403,6 +407,15 @@ static void destroy_async_data(struct Curl_async *async)
 
       free(async->os_specific);
     }
+#ifdef HAVE_SOCKETPAIR
+    /*
+     * ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
+     * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
+     */
+    if(conn)
+      Curl_multi_closed(conn->data, sock_rd);
+    sclose(sock_rd);
+#endif
   }
   async->os_specific = NULL;
 
@@ -644,6 +657,8 @@ int Curl_resolver_getsock(struct connectdata *conn,
   if(td) {
     /* return read fd to client for polling the DNS resolution status */
     socks[0] = td->tsd.sock_pair[0];
+    DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn);
+    td->tsd.conn = conn;
     ret_val = GETSOCK_READSOCK(0);
   }
   else {
-- 
EW
-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette:   https://curl.haxx.se/mail/etiquette.html
Received on 2019-08-11