mirror of
https://github.com/curl/curl.git
synced 2026-08-24 23:33:33 +03:00
curl: timeout in the read callback
The read callback can timeout if there's nothing to read within the given maximum period. Example use case is when doing "curl -m 3 telnet://example.com" or anything else that expects input on stdin or similar that otherwise would "hang" until something happens and then not respect the timeout. This fixes KNOWN_BUG 8.1, first filed in July 2009. Bug: https://sourceforge.net/p/curl/bugs/846/ Closes #9815
This commit is contained in:
parent
b830f9ba9e
commit
a55256cfb2
9 changed files with 58 additions and 29 deletions
|
|
@ -23,6 +23,10 @@
|
|||
***************************************************************************/
|
||||
#include "tool_setup.h"
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#define ENABLE_CURLX_PRINTF
|
||||
/* use our own printf() functions */
|
||||
#include "curlx.h"
|
||||
|
|
@ -30,6 +34,7 @@
|
|||
#include "tool_cfgable.h"
|
||||
#include "tool_cb_rea.h"
|
||||
#include "tool_operate.h"
|
||||
#include "tool_util.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
|
|
@ -39,8 +44,36 @@
|
|||
|
||||
size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
{
|
||||
ssize_t rc;
|
||||
ssize_t rc = 0;
|
||||
struct InStruct *in = userdata;
|
||||
struct OperationConfig *config = in->config;
|
||||
|
||||
if(config->timeout_ms) {
|
||||
struct timeval now = tvnow();
|
||||
long msdelta = tvdiff(now, in->per->start);
|
||||
|
||||
if(msdelta > config->timeout_ms)
|
||||
/* timeout */
|
||||
return 0;
|
||||
#ifndef WIN32
|
||||
/* this logic waits on read activity on a file descriptor that is not a
|
||||
socket which makes it not work with select() on Windows */
|
||||
else {
|
||||
fd_set bits;
|
||||
struct timeval timeout;
|
||||
long wait = config->timeout_ms - msdelta;
|
||||
|
||||
/* wait this long at the most */
|
||||
timeout.tv_sec = wait/1000;
|
||||
timeout.tv_usec = (wait%1000)*1000;
|
||||
|
||||
FD_ZERO(&bits);
|
||||
FD_SET(in->fd, &bits);
|
||||
if(!select(in->fd + 1, &bits, NULL, NULL, &timeout))
|
||||
return 0; /* timeout */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
rc = read(in->fd, buffer, sz*nmemb);
|
||||
if(rc < 0) {
|
||||
|
|
@ -53,6 +86,8 @@ size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
|||
rc = 0;
|
||||
}
|
||||
in->config->readbusy = FALSE;
|
||||
|
||||
/* when select() rerturned zero here, it timed out */
|
||||
return (size_t)rc;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue