aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/multi.c5
-rw-r--r--lib/transfer.c21
-rw-r--r--lib/transfer.h5
3 files changed, 24 insertions, 7 deletions
diff --git a/lib/multi.c b/lib/multi.c
index 8bb93660d..c471c48d9 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -1810,6 +1810,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
{
char *newurl = NULL;
bool retry = FALSE;
+ bool comeback = FALSE;
/* check if over send speed */
if((data->set.max_send_speed > 0) &&
@@ -1844,7 +1845,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
/* read/write data if it is ready to do so */
- result = Curl_readwrite(data->easy_conn, data, &done);
+ result = Curl_readwrite(data->easy_conn, data, &done, &comeback);
k = &data->req;
@@ -1950,6 +1951,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
rc = CURLM_CALL_MULTI_PERFORM;
}
}
+ else if(comeback)
+ rc = CURLM_CALL_MULTI_PERFORM;
free(newurl);
break;
diff --git a/lib/transfer.c b/lib/transfer.c
index f5987feb2..82a961f0e 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -384,11 +384,15 @@ bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
* Go ahead and do a read if we have a readable socket or if
* the stream was rewound (in which case we have data in a
* buffer)
+ *
+ * return '*comeback' TRUE if we didn't properly drain the socket so this
+ * function should get called again without select() or similar in between!
*/
static CURLcode readwrite_data(struct Curl_easy *data,
struct connectdata *conn,
struct SingleRequest *k,
- int *didwhat, bool *done)
+ int *didwhat, bool *done,
+ bool *comeback)
{
CURLcode result = CURLE_OK;
ssize_t nread; /* number of bytes read */
@@ -398,6 +402,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
int maxloops = 100;
*done = FALSE;
+ *comeback = FALSE;
/* This is where we loop until we have read everything there is to
read or we get a CURLE_AGAIN */
@@ -804,6 +809,12 @@ static CURLcode readwrite_data(struct Curl_easy *data,
} while(data_pending(conn) && maxloops--);
+ if(maxloops <= 0) {
+ /* we mark it as read-again-please */
+ conn->cselect_bits = CURL_CSELECT_IN;
+ *comeback = TRUE;
+ }
+
if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
conn->bits.close) {
/* When we've read the entire thing and the close bit is set, the server
@@ -1029,10 +1040,14 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
/*
* Curl_readwrite() is the low-level function to be called when data is to
* be read and written to/from the connection.
+ *
+ * return '*comeback' TRUE if we didn't properly drain the socket so this
+ * function should get called again without select() or similar in between!
*/
CURLcode Curl_readwrite(struct connectdata *conn,
struct Curl_easy *data,
- bool *done)
+ bool *done,
+ bool *comeback)
{
struct SingleRequest *k = &data->req;
CURLcode result;
@@ -1077,7 +1092,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if((k->keepon & KEEP_RECV) &&
((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) {
- result = readwrite_data(data, conn, k, &didwhat, done);
+ result = readwrite_data(data, conn, k, &didwhat, done, comeback);
if(result || *done)
return result;
}
diff --git a/lib/transfer.h b/lib/transfer.h
index 0e253e373..0058f8c86 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -40,10 +40,9 @@ typedef enum {
CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
followtype type);
-
-
CURLcode Curl_readwrite(struct connectdata *conn,
- struct Curl_easy *data, bool *done);
+ struct Curl_easy *data, bool *done,
+ bool *comeback);
int Curl_single_getsock(const struct connectdata *conn,
curl_socket_t *socks,
int numsocks);