(FTP) a failed upload does not invalidate the control connection
authorDaniel Stenberg <daniel@haxx.se>
Thu, 21 Sep 2006 20:52:58 +0000 (20:52 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 21 Sep 2006 20:52:58 +0000 (20:52 +0000)
CHANGES
RELEASE-NOTES
lib/ftp.c
lib/multi.c

diff --git a/CHANGES b/CHANGES
index 971a52f..90ec2f0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,12 @@
 
                                   Changelog
 
+Daniel (21 September 2006)
+- Added test case 531 in an attempt to repeat bug report #1561470
+  (http://curl.haxx.se/bug/view.cgi?id=1561470) that is said to crash when an
+  FTP upload fails with the multi interface. It did not, but I made a failed
+  upload still assume the control connection to be fine.
+
 Daniel (20 September 2006)
 - Armel Asselin fixed problems when you gave a proxy URL with user name and
   empty password or no password at all. Test case 278 and 279 were added to
index 19c9940..0bcb561 100644 (file)
@@ -21,6 +21,7 @@ This release includes the following changes:
 
 This release includes the following bugfixes:
 
+ o (FTP) a failed upload does not invalidate the control connection
  o proxy URL with user name and empty password or no password at all now work
  o fixed a socket state problem with *multi_socket()
  o (HTTP) NTLM hostname fix
index 44dcf93..48b66b3 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -2997,6 +2997,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
   case CURLE_FTP_PORT_FAILED:
   case CURLE_FTP_COULDNT_SET_BINARY:
   case CURLE_FTP_COULDNT_RETR_FILE:
+  case CURLE_FTP_COULDNT_STOR_FILE:
   case CURLE_FTP_ACCESS_DENIED:
     /* the connection stays alive fine even though this happened */
     /* fall-through */
@@ -3351,7 +3352,7 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
     result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
 
   /* end of transfer */
-  DEBUGF(infof(data, "DO-MORE phase ends\n"));
+  DEBUGF(infof(data, "DO-MORE phase ends with %d\n", result));
 
   return result;
 }
index 2da17a3..0a19c12 100644 (file)
@@ -512,7 +512,15 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
     if(easy->easy_conn) {
       /* Set up the association right */
       easy->easy_conn->data = easy->easy_handle;
+
+      /* Curl_done() clears the conn->data field to lose the association
+         between the easy handle and the connection */
       Curl_done(&easy->easy_conn, easy->result);
+
+      if(easy->easy_conn)
+        /* the connection is still alive, set back the association to enable
+           the check below to trigger TRUE */
+        easy->easy_conn->data = easy->easy_handle;
     }
 
     /* If this easy_handle was the last one in charge for one or more
@@ -528,8 +536,8 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
 
        Thus, we need to check for all connections in the shared cache that
        points to this handle and are using PROT_CLOSEACTION. If there's any,
-       we need to add this handle to the list of "easy_handls kept around for
-       nice closure".
+       we need to add this handle to the list of "easy handles kept around for
+       nice connection closures".
      */
     if(multi_conn_using(multi, easy->easy_handle))
       /* There's at least one connection using this handle so we must keep
@@ -1011,6 +1019,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
 
         if(CURLE_OK == easy->result)
           easy->result = Curl_readwrite_init(easy->easy_conn);
+        else
+          /* Remove ourselves from the send pipeline */
+          Curl_removeHandleFromPipeline(easy->easy_handle,
+                                        easy->easy_conn->send_pipe);
 
         if(CURLE_OK == easy->result) {
           multistate(easy, CURLM_STATE_DO_DONE);
@@ -1167,10 +1179,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       break;
 
     case CURLM_STATE_COMPLETED:
-      if (easy->easy_handle->state.cancelled) {
+      if (easy->easy_handle->state.cancelled)
         /* Go into the CANCELLED state if we were cancelled */
         multistate(easy, CURLM_STATE_CANCELLED);
-      }
 
       /* this is a completed transfer, it is likely to still be connected */