]> granicus.if.org Git - curl/commitdiff
multi_socket: react on socket close immediately
authorDaniel Stenberg <daniel@haxx.se>
Wed, 19 Jun 2013 21:54:28 +0000 (23:54 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 20 Jun 2013 20:36:52 +0000 (22:36 +0200)
As a remedy to the problem when a socket gets closed and a new one is
opened with the same file descriptor number and as a result
multi.c:singlesocket() doesn't detect the difference, the new function
Curl_multi_closed() gets told when a socket is closed so that it can be
removed from the socket hash. When the old one has been removed, a new
socket should be detected fine by the singlesocket() on next invoke.

Bug: http://curl.haxx.se/bug/view.cgi?id=1248
Reported-by: Erik Johansson
lib/connect.c
lib/multi.c
lib/multiif.h

index 2d5b641af4648a7d482e47e8a2f838e57d4accbc..be8c0e45a8c071dff4fda0140cafe493a4157794 100644 (file)
@@ -1239,7 +1239,7 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
  * 'conn' can be NULL, beware!
  */
 int Curl_closesocket(struct connectdata *conn,
-                     curl_socket_t sock)
+                      curl_socket_t sock)
 {
   if(conn && conn->fclosesocket) {
     if((sock == conn->sock[SECONDARYSOCKET]) &&
@@ -1251,7 +1251,13 @@ int Curl_closesocket(struct connectdata *conn,
     else
       return conn->fclosesocket(conn->closesocket_client, sock);
   }
-  return sclose(sock);
+  sclose(sock);
+
+  if(conn)
+    /* tell the multi-socket code about this */
+    Curl_multi_closed(conn, sock);
+
+  return 0;
 }
 
 /*
index 25efce154a7e1aa78ddf0dba9ecb5f746a470352..09a5b2d8b3c57b07253b2e2496b08276a8616ce3 100644 (file)
@@ -2051,6 +2051,39 @@ static void singlesocket(struct Curl_multi *multi,
   easy->numsocks = num;
 }
 
+/*
+ * Curl_multi_closed()
+ *
+ * Used by the connect code to tell the multi_socket code that one of the
+ * sockets we were using have just been closed.  This function will then
+ * remove it from the sockethash for this handle to make the multi_socket API
+ * behave properly, especially for the case when libcurl will create another
+ * socket again and it gets the same file descriptor number.
+ */
+
+void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
+{
+  struct Curl_multi *multi = conn->data->multi;
+  if(multi) {
+    /* this is set if this connection is part of a handle that is added to
+       a multi handle, and only then this is necessary */
+    struct Curl_sh_entry *entry =
+      Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+
+    if(entry) {
+      if(multi->socket_cb)
+        multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
+                         multi->socket_userp,
+                         entry->socketp);
+
+      /* now remove it from the socket hash */
+      sh_delentry(multi->sockhash, s);
+    }
+  }
+}
+
+
+
 /*
  * add_next_timeout()
  *
index 799daebcc195f0dc3b278ce048b0851a3989dd1b..d1b0e2fb3238b8a0e0add36cb373fd26a4262513 100644 (file)
@@ -83,4 +83,16 @@ struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi);
 /* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
 size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
 
+/*
+ * Curl_multi_closed()
+ *
+ * Used by the connect code to tell the multi_socket code that one of the
+ * sockets we were using have just been closed.  This function will then
+ * remove it from the sockethash for this handle to make the multi_socket API
+ * behave properly, especially for the case when libcurl will create another
+ * socket again and it gets the same file descriptor number.
+ */
+
+void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
+
 #endif /* HEADER_CURL_MULTIIF_H */