summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/transfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/transfer.c')
-rw-r--r--libs/libcurl/src/transfer.c45
1 files changed, 31 insertions, 14 deletions
diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c
index 8fe343e0bd..44e5f03cea 100644
--- a/libs/libcurl/src/transfer.c
+++ b/libs/libcurl/src/transfer.c
@@ -40,9 +40,7 @@
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
-#ifdef HAVE_SIGNAL_H
#include <signal.h>
-#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
@@ -671,7 +669,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
k->bytecount += nread;
max_recv -= nread;
- Curl_pgrsSetDownloadCounter(data, k->bytecount);
+ result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
+ if(result)
+ goto out;
if(!k->chunk && (nread || k->badheader || is_empty_data)) {
/* If this is chunky transfer, it was already written */
@@ -700,19 +700,15 @@ static CURLcode readwrite_data(struct Curl_easy *data,
in http_chunks.c.
Make sure that ALL_CONTENT_ENCODINGS contains all the
encodings handled here. */
- if(data->set.http_ce_skip || !k->writer_stack) {
- if(!k->ignorebody && nread) {
+ if(!k->ignorebody && nread) {
#ifndef CURL_DISABLE_POP3
- if(conn->handler->protocol & PROTO_FAMILY_POP3)
- result = Curl_pop3_write(data, k->str, nread);
- else
+ if(conn->handler->protocol & PROTO_FAMILY_POP3)
+ result = Curl_pop3_write(data, k->str, nread);
+ else
#endif /* CURL_DISABLE_POP3 */
- result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
- nread);
- }
+ result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
+ nread);
}
- else if(!k->ignorebody && nread)
- result = Curl_unencode_write(data, k->writer_stack, k->str, nread);
}
k->badheader = HEADER_NORMAL; /* taken care of now */
@@ -1050,6 +1046,19 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
return CURLE_OK;
}
+static int select_bits_paused(struct Curl_easy *data, int select_bits)
+{
+ /* See issue #11982: we really need to be careful not to progress
+ * a transfer direction when that direction is paused. Not all parts
+ * of our state machine are handling PAUSED transfers correctly. So, we
+ * do not want to go there.
+ * NOTE: we are only interested in PAUSE, not HOLD. */
+ return (((select_bits & CURL_CSELECT_IN) &&
+ (data->req.keepon & KEEP_RECV_PAUSE)) ||
+ ((select_bits & CURL_CSELECT_OUT) &&
+ (data->req.keepon & KEEP_SEND_PAUSE)));
+}
+
/*
* Curl_readwrite() is the low-level function to be called when data is to
* be read and written to/from the connection.
@@ -1068,12 +1077,20 @@ CURLcode Curl_readwrite(struct connectdata *conn,
int didwhat = 0;
int select_bits;
-
if(data->state.dselect_bits) {
+ if(select_bits_paused(data, data->state.dselect_bits)) {
+ /* leave the bits unchanged, so they'll tell us what to do when
+ * this transfer gets unpaused. */
+ DEBUGF(infof(data, "readwrite, dselect_bits, early return on PAUSED"));
+ result = CURLE_OK;
+ goto out;
+ }
select_bits = data->state.dselect_bits;
data->state.dselect_bits = 0;
}
else if(conn->cselect_bits) {
+ /* CAVEAT: adding `select_bits_paused()` check here makes test640 hang
+ * (among others). Which hints at strange state handling in FTP land... */
select_bits = conn->cselect_bits;
conn->cselect_bits = 0;
}