Commit Graph

373 Commits

Author SHA1 Message Date
Daniel Stenberg d1b56d0043 multi_runsingle: fix possible memory leak
Coverity CID 1202837. 'newurl' can in fact be allocated even when
Curl_retry_request() returns failure so free it if need be.
2014-10-07 13:57:13 +02:00
Daniel Stenberg b0bfae1963 curl_multi_remove_handle: remove dead code
Coverify CID 1157776. Removed a superfluous if() that always evaluated
true (and an else clause that never ran), and then re-indented the
function accordingly.
2014-10-03 23:46:10 +02:00
Daniel Stenberg 0d357155cc multi_runsingle: fix memory leak
Coverity CID 1202837. There's a potential risk that 'newurl' gets
overwritten when it was already pointing to allocated memory.
2014-10-02 23:22:01 +02:00
Steve Holme 4a6fa4c204 multi.c: Avoid invalid memory read after free() from commit 3c8c873252
As the current element in the list is free()d by Curl_llist_remove(),
when the associated connection is pending, reworked the loop to avoid
accessing the next element through e->next afterward.
2014-09-07 07:11:14 +01:00
Steve Holme c25cd9094b multi.c: Fixed compilation warning from commit 3c8c873252
warning: implicit conversion from enumeration type 'CURLMcode' to
different enumeration type 'CURLcode'
2014-09-07 00:21:36 +01:00
Daniel Stenberg a6c48c8be7 curl_multi_cleanup: remove superfluous NULL assigns
... as the struct is free()d in the end anyway. It was first pointed out
to me that one of the ->msglist assignments were supposed to have been
->pending but was a copy and paste mistake when I realized none of the
clearing of pointers had to be there.
2014-09-02 23:44:42 +02:00
Daniel Stenberg 3c8c873252 multi: convert CURLM_STATE_CONNECT_PEND handling to a list
... instead of scanning through all handles, stash only the actual
handles that are in that state in the new ->pending list and scan that
list only. It should be mostly empty or very short. And only used for
pipelining.

This avoids a rather hefty slow-down especially notable if you add many
handles to the same multi handle. Regression introduced in commit
0f147887 (version 7.30.0).

Bug: http://curl.haxx.se/mail/lib-2014-07/0206.html
Reported-by: David Meyer
2014-09-02 10:17:47 +02:00
Daniel Stenberg cacdc27f52 low-speed-limit: avoid timeout flood
Introducing Curl_expire_latest(). To be used when we the code flow only
wants to get called at a later time that is "no later than X" so that
something can be checked (and another timeout be added).

The low-speed logic for example could easily be made to set very many
expire timeouts if it would be called faster or sooner than what it had
set its own timer and this goes for a few other timers too that aren't
explictiy checked for timer expiration in the code.

If there's no condition the code that says if(time-passed >= TIME), then
Curl_expire_latest() is preferred to Curl_expire().

If there exists such a condition, it is on the other hand important that
Curl_expire() is used and not the other.

Bug: http://curl.haxx.se/mail/lib-2014-06/0235.html
Reported-by: Florian Weimer
2014-08-31 23:50:01 +02:00
Michael Wallner 09b5a99816 resolve: cache lookup for async resolvers
While waiting for a host resolve, check if the host cache may have
gotten the name already (by someone else), for when the same name is
resolved by several simultanoues requests.

The resolver thread occasionally gets stuck in getaddrinfo() when the
DNS or anything else is crappy or slow, so when a host is found in the
DNS cache, leave the thread alone and let itself cleanup the mess.
2014-08-31 10:49:40 +02:00
Daniel Stenberg a4cece3d47 CONNECT: Revert Curl_proxyCONNECT back to 7.29.0 design
This reverts commit cb3e6dfa35 and instead fixes the problem
differently.

The reverted commit addressed a test failure in test 1021 by simplifying
and generalizing the code flow in a way that damaged the
performance. Now we modify the flow so that Curl_proxyCONNECT() again
does as much as possible in one go, yet still do test 1021 with and
without valgrind. It failed due to mistakes in the multi state machine.

Bug: http://curl.haxx.se/bug/view.cgi?id=1397
Reported-by: Paul Saab
2014-07-22 23:00:19 +02:00
Ray Satiro 907520c4b9 progress callback: skip last callback update on errors
When an error has been detected, skip the final forced call to the
progress callback by making sure to pass the current return code
variable in the Curl_done() call in the CURLM_STATE_DONE state.

This avoids the "extra" callback that could occur even if you returned
error from the progress callback.

Bug: http://curl.haxx.se/mail/lib-2014-06/0062.html
Reported by: Jonathan Cardoso Machado
2014-07-02 23:53:25 +02:00
Daniel Stenberg df13f8e8c2 bits.close: introduce connection close tracking
Make all code use connclose() and connkeep() when changing the "close
state" for a connection. These two macros take a string argument with an
explanation, and debug builds of curl will include that in the debug
output. Helps tracking connection re-use/close issues.
2014-05-22 00:34:10 +02:00
Daniel Stenberg 84bd19ffd4 timers: fix timer regression involving redirects / reconnects
In commit 0b3750b5c2 (released in 7.36.0) we fixed a timeout issue
but instead broke the timings.

To fix this, I introduce a new timestamp to use for the timeouts and
restored the previous timestamp and timestamp position so that the old
timer functionality is restored.

In addition to that, that change also broke connection timeouts for when
more than one connect was used (as it would then count the total time
from the first connect and not for the most recent one). Now
Curl_timeleft() has been modified so that it checks against different
start times depending on which timeout it checks.

Test 1303 is updated accordingly.

Bug: http://curl.haxx.se/mail/lib-2014-05/0147.html
Reported-by: Ryan Braud
2014-05-15 21:28:19 +02:00
Jeff King 37f484276d curl_multi_cleanup: ignore SIGPIPE better
When looping and closing each individual connection left open, the
SIGPIPE ignoring was not done and could thus lead to death by signal 13.

Bug: http://thread.gmane.org/gmane.comp.version-control.git/238242
2014-05-05 12:47:46 +02:00
Daniel Stenberg d5ec44ca4c INFILESIZE: fields in UserDefined must not be changed run-time
set.infilesize in this case was modified in several places, which could
lead to repeated requests using the same handle to get unintendent/wrong
consequences based on what the previous request did!
2014-04-26 18:17:10 +02:00
Marc Hoersken ee6791128f multi.c: fix possible invalid memory access in case nfds overflows
ufds might not be allocated in case nfds overflows to zero while
extra_nfds is still non-zero. udfs is then accessed within the
extra_nfds-based for loop.
2014-04-19 16:02:14 +02:00
Daniel Stenberg 0b3750b5c2 multi_runsingle: move timestamp into INIT
Setting the TIMER_STARTSINGLE timestamp first in CONNECT has the
drawback that for actions that go back to the CONNECT state, the time
stamp is reset and for the multi_socket API there's no corresponding
Curl_expire() then so the timeout logic gets wrong!

Reported-by: Brad Spencer
Bug: http://curl.haxx.se/mail/lib-2014-02/0036.html
2014-03-03 16:35:04 +01:00
Daniel Stenberg 854aca5420 multi: ignore sigpipe internally
When the multi API is used we must also ignore SIGPIPE signals when
caused by things we do, like they can easily be generated by OpenSSL.
2014-02-17 10:35:21 +01:00
Shao Shuchao 2111c2ed07 ConnectionDone: default maxconnects to 4 x number of easy handles
... as documented!
2014-02-17 09:29:25 +01:00
Dan Fandrich c631a54bb6 ftp: fixed a memory leak on wildcard error path 2014-01-30 22:15:03 +01:00
Dan Fandrich da9864fb72 multi: Fixed a memory leak on OOM condition 2014-01-24 00:22:08 +01:00
Colin Hogben bbc1705fa9 error message: Sensible message on timeout when transfer size unknown
A transfer timeout could result in an error message such as "Operation
timed out after 3000 milliseconds with 19 bytes of -1 received".  This
patch removes the non-sensical "of -1" when the size of the transfer
is unknown, mirroring the logic in lib/transfer.c
2014-01-13 16:54:10 +01:00
Daniel Stenberg 3b183df9cc multi: remove MULTI_TIMEOUT_INACCURACY
With the recently added timeout "reminder" functionality, there's no
reason left for us to execute timeout code before the time is
ripe. Simplifies the handling too.

This will make the *TIMEOUT and *CONNECTTIMEOUT options more accurate
again, which probably is most important when the *_MS versions are used.

In multi_socket, make sure to update 'now' after having handled activity
on a socket.
2014-01-12 00:11:53 +01:00
Daniel Stenberg 980659a2ca multi_socket: remind app if timeout didn't run
BACKGROUND:

We have learned that on some systems timeout timers are inaccurate and
might occasionally fire off too early. To make the multi_socket API work
with this, we made libcurl execute timeout actions a bit early too if
they are within our MULTI_TIMEOUT_INACCURACY. (added in commit
2c72732ebf, present since 7.21.0)

Switching everything to the multi API made this inaccuracy problem
slightly more notable as now everyone can be affected.

Recently (commit 21091549c0) we tweaked that inaccuracy value to make
timeouts more accurate and made it platform specific. We also figured
out that we have code at places that check for fixed timeout values so
they MUST NOT run too early as then they will not trigger at all (see
commit be28223f35 and a691e04470) - so there are definitately problems
with running timeouts before they're supposed to run. (We've handled
that so far by adding the inaccuracy margin to those specific timeouts.)

The libcurl multi_socket API tells the application with a callback that
a timeout expires in N milliseconds (and it explicitly will not tell it
again for the same timeout), and the application is then supposed to
call libcurl when that timeout expires. When libcurl subsequently gets
called with curl_multi_socket_action(...CURL_SOCKET_TIMEOUT...), it
knows that the application thinks the timeout expired - and alas, if it
is within the inaccuracy level libcurl will run code handling that
handle.

If the application says CURL_SOCKET_TIMEOUT to libcurl and _isn't_
within the inaccuracy level, libcurl will not consider the timeout
expired and it will not tell the application again since the timeout
value is still the same.

NOW:

This change introduces a modified behavior here. If the application says
CURL_SOCKET_TIMEOUT and libcurl finds no timeout code to run, it will
inform the application about the timeout value - *again* even if it is
the same timeout that it already told about before (although libcurl
will of course tell it the updated time so that it'll still get the
correct remaining time). This way, we will not risk that the application
believes it has done its job and libcurl thinks the time hasn't come yet
to run any code and both just sit waiting. This also allows us to
decrease the MULTI_TIMEOUT_INACCURACY margin, but that will be handled
in a separate commit.

A repeated timeout update to the application risk that the timeout will
then fire again immediately and we have what basically is a busy-loop
until the time is fine even for libcurl. If that becomes a problem, we
need to address it.
2014-01-10 13:57:25 +01:00
Marc Hoersken 61312fe66f multi.c: fix possible dereference of null pointer 2014-01-05 20:01:33 +01:00
Daniel Stenberg bf24b64e83 progresscallback: make CURLE_ABORTED_BY_CALLBACK get returned better
When the progress callback returned 1 at a very early state, the code
would not make CURLE_ABORTED_BY_CALLBACK get returned but the process
would still be interrupted. In the HTTP case, this would then cause a
CURLE_GOT_NOTHING to erroneously get returned instead.

Reported-by: Petr Novak
Bug: http://curl.haxx.se/bug/view.cgi?id=1318
2014-01-03 14:09:59 +01:00
Steve Holme 60bd22620a mprintf: Replaced internal usage of FORMAT_OFF_T and FORMAT_OFF_TU
Following commit 0aafd77fa4, replaced the internal usage of
FORMAT_OFF_T and FORMAT_OFF_TU with the external versions that we
expect API programmers to use.

This negates the need for separate definitions which were subtly
different under different platforms/compilers.
2013-12-31 11:10:42 +00:00
Daniel Stenberg 2715d7f948 FILE: don't wait due to CURLOPT_MAX_RECV_SPEED_LARGE
The FILE:// code doesn't support this option - and it doesn't make sense
to support it as long as it works as it does since then it'd only block
even longer.

But: setting CURLOPT_MAX_RECV_SPEED_LARGE would make the transfer first
get done and then libcurl would wait until the average speed would get
low enough. This happened because the transfer happens completely in the
DO state for FILE:// but then it would still unconditionally continue in
to the PERFORM state where the speed check is made.

Starting now, the code will skip from DO_DONE to DONE immediately if no
socket is set to be recv()ed or send()ed to.

Bug: http://curl.haxx.se/bug/view.cgi?id=1312
Reported-by: Mohammad AlSaleh
2013-12-22 23:44:14 +01:00
Steve Holme d92de3a7e9 multi.c: Fixed compilation warning
warning: declaration of 'pipe' shadows a global declaration
2013-12-01 20:22:57 +00:00
Steve Holme 26ff1ea6c3 multi.c: Fixed compilation error introduced in commit a900d45489
Systems that define SIGPIPE_VARIABLE as a noop would not compile as
restore_pipe was defined afterwards.
2013-11-27 23:45:45 +00:00
Jeff King a900d45489 curl_multi_cleanup: ignore SIGPIPE
This is an extension to the fix in 7d80ed64e4. We may
call Curl_disconnect() while cleaning up the multi handle,
which could lead to openssl sending packets, which could get
a SIGPIPE.

Signed-off-by: Jeff King <peff@peff.net>
2013-11-27 22:47:12 +01:00
Steve Holme 65ce9b6d6c multi: Small code tidy up to avoid hard return 2013-11-12 09:59:22 +00:00
Björn Stenberg fa1253aee1 multi: Set read socket when returning READSOCK(0)
This patch fixes and issue introduced in commit 7d7df83198, if the
tunnel state was TUNNEL_CONNECT, waitconnect_getsock() would return a
bitmask indicating a readable socket but never stored the socket in the
return array.
2013-11-11 23:41:44 +00:00
Björn Stenberg 02fbc26d59 connect: Add connection delay to Happy Eyeballs.
This patch adds a 200ms delay between the first and second address
family socket connection attempts.

It also iterates over IP addresses in the order returned by the
system, meaning most dual-stack systems will try IPv6 first.

Additionally, it refactors the connect code, removing most code that
handled synchronous connects. Since all sockets are now non-blocking,
the logic can be made simpler.
2013-11-04 22:38:19 +01:00
Daniel Stenberg 753d44fa00 curl_multi_wait: accept 0 from multi_timeout() as valid timeout
The code rejected 0 as a valid timeout while in fact the function could
indeed legitimately return that and it should be respected.

Reported-by: Bjorn Stenberg
2013-10-30 23:48:08 +01:00
Björn Stenberg 7d7df83198 Add "Happy Eyeballs" for IPv4/IPv6.
This patch invokes two socket connect()s nearly simultaneously, and
the socket that is first connected "wins" and is subsequently used for
the connection. The other is terminated.

There is a very slight IPv4 preference, in that if both sockets connect
simultaneously IPv4 is checked first and thus will win.
2013-10-27 11:19:53 +01:00
Daniel Stenberg 84f3b3dd44 curl_multi_remove_handle: allow multiple removes
When removing an already removed handle, avoid that to ruin the
internals and just return OK instead.
2013-08-29 22:08:45 +02:00
Daniel Stenberg a691e04470 multi_socket: improved 100-continue timeout handling
When waiting for a 100-continue response from the server, the
Curl_readwrite() will refuse to run if called until the timeout has been
reached.

We timeout code in multi_socket() allows code to run slightly before the
actual timeout time, so for test 154 it could lead to the function being
executed but refused in Curl_readwrite() and then the application would
just sit idling forever.

This was detected with runtests.pl -e on test 154.
2013-08-28 00:07:12 +02:00
Daniel Stenberg 22adb46a32 multi: move on from STATE_DONE faster
Make sure we always return CURLM_CALL_MULTI_PERFORM when we reach
CURLM_STATE_DONE since the state is transient and it can very well
continue executing as there is nothing to wait for.

Bug: http://curl.haxx.se/mail/lib-2013-08/0211.html
Reported-by: Yi Huang
2013-08-22 22:55:25 +02:00
Daniel Stenberg 19122c0768 CURLM_ADDED_ALREADY: new error code
Doing curl_multi_add_handle() on an easy handle that is already added to
a multi handle now returns this error code. It previously returned
CURLM_BAD_EASY_HANDLE for this condition.
2013-08-20 23:13:19 +02:00
Daniel Stenberg c346c4c8f9 multi_init: moved init code here from add_handle
The closure_handle is "owned" by the multi handle and it is
unconditional so the setting up of it should be in the Curl_multi_handle
function rather than curl_multi_add_handle.
2013-08-20 23:13:19 +02:00
Daniel Stenberg bc7d806e3a multi: remove dns cache creation code from *add_handle
As it is done unconditionally in multi_init() this code will never run!
2013-08-20 23:13:19 +02:00
Daniel Stenberg 2ae3d28f3d multi: s/easy/data
With everything being struct SessionHandle pointers now, this rename
makes multi.c use the library-wide practise of calling that pointer
'data' instead of the previously used 'easy'.
2013-08-12 13:52:58 +02:00
Daniel Stenberg 8a42c2ef8d cleanup: removed one function, made one static
Moved Curl_easy_addmulti() from easy.c to multi.c, renamed it to
easy_addmulti and made it static.

Removed Curl_easy_initHandleData() and uses of it since it was emptied
in commit cdda92ab67b47d74a.
2013-08-12 13:17:57 +02:00
Daniel Stenberg 2af0b10c95 comments: remove old and wrong multi/easy interface statements 2013-08-09 23:39:09 +02:00
Daniel Stenberg d2b36e466a global dns cache: didn't work [regression]
CURLOPT_DNS_USE_GLOBAL_CACHE broke in commit c43127414d (been
broken since the libcurl 7.29.0 release). While this option has been
documented as deprecated for almost a decade and nobody even reported
this bug, it should remain functional.

Added test case 1512 to verify
2013-08-08 16:28:46 +02:00
Daniel Stenberg 7cc00d9a83 FTP: when EPSV gets a 229 but fails to connect, retry with PASV
This is a regression as this logic used to work. It isn't clear when it
broke, but I'm assuming in 7.28.0 when we went all-multi internally.

This likely never worked with the multi interface. As the failed
connection is detected once the multi state has reached DO_MORE, the
Curl_do_more() function was now expanded somewhat so that the
ftp_do_more() function can request to go "back" to the previous state
when it makes another attempt - using PASV.

Added test case 1233 to verify this fix. It has the little issue that it
assumes no service is listening/accepting connections on port 1...

Reported-by: byte_bucket in the #curl IRC channel
2013-08-06 09:57:59 +02:00
Daniel Stenberg eb41e8eebe multi: remove the one_easy struct field
Since the merge of SessionHandle with Curl_one_easy, this indirection
isn't used anymore.
2013-08-03 22:51:35 +02:00
Daniel Stenberg 3cd43bbfec multi: rename all Curl_one_easy to SessionHandle 2013-08-03 22:51:35 +02:00
Daniel Stenberg 204e340bcd multi: remove the multi_pos struct field
Since Curl_one_easy is really a SessionHandle now, this indirection
doesn't exist anymore.
2013-08-03 22:51:35 +02:00