diff --git a/CHANGES b/CHANGES index 971a52f2f..90ec2f095 100644 --- 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 diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 19c994079..0bcb561ff 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -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 diff --git a/lib/ftp.c b/lib/ftp.c index 44dcf9340..48b66b363 100644 --- 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; } diff --git a/lib/multi.c b/lib/multi.c index 2da17a3f0..0a19c129e 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -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 */