Merge lp:~marcustomlinson/net-cpp/fix_ppc_timeout into lp:net-cpp

Proposed by Marcus Tomlinson
Status: Merged
Approved by: Paweł Stołowski
Approved revision: 45
Merged at revision: 44
Proposed branch: lp:~marcustomlinson/net-cpp/fix_ppc_timeout
Merge into: lp:net-cpp
Diff against target: 16 lines (+5/-1)
1 file modified
src/core/net/http/impl/curl/request.h (+5/-1)
To merge this branch: bzr merge lp:~marcustomlinson/net-cpp/fix_ppc_timeout
Reviewer Review Type Date Requested Status
Michi Henning (community) Approve
Thomas Voß (community) Approve
Review via email: mp+247100@code.launchpad.net

Commit message

Explicitly cast milliseconds::count() to long.

Description of the change

Explicitly cast milliseconds::count() to long.

On PPC, this method returns an 8-byte long long, of which libCurl is hardcoded to read only the first 4 bytes. Furthermore, PPC being Big Endian means that the first 4 bytes will be 0 for any number lower than 2147483648.

To post a comment you must log in.
Revision history for this message
Thomas Voß (thomas-voss) wrote :

LGTM.

review: Approve
Revision history for this message
Michi Henning (michihenning) wrote :

It would be ultra-cool to have a timeout test in the test suite.

Revision history for this message
Michi Henning (michihenning) wrote :

I finally got net-cpp to work with Thomas's help. Issue is that net-cpp needs libcurl4-openssl-dev.

We really need to add that to debian/control. Not sure about the other ssl options that libcurl supports. There is a whole bunch of them, including OpenSSL and gnutls.

Anyway, with the patched net-cpp, the timeout exception in the HttpClient test now is delivered correctly, and the test passes.

Revision history for this message
Michi Henning (michihenning) wrote :

I'm having second thoughts about this fix as it stands. If someone accidentally passes a duration that is greater than numeric_limits<long>::max() (such as the epoch), we'll wait a random amount of time (possibly not at all or a very short amount of time), depending on the exact value.
I can see three options:

- Check if the passed value overflows and silently clamp to numeric_limits<long>::max()

- Check if the passed value overflows and silently adjust to "wait forever"

- Throw an exception

I'm slightly in favour of the second option. That's because the max value amounts to a wait time of a little over 24 days. If someone is prepared to wait that long for an HTTP request to complete, it is probably safe to assume that they are willing to wait forever.

review: Needs Fixing
Revision history for this message
Michi Henning (michihenning) wrote :

I'm having second thoughts about this fix as it stands. If someone accidentally passes a duration that is greater than numeric_limits<long>::max() (such as the epoch), we'll wait a random amount of time (possibly not at all or a very short amount of time), depending on the exact value.
I can see three options:

- Check if the passed value overflows and silently clamp to numeric_limits<long>::max()

- Check if the passed value overflows and silently adjust to "wait forever"

- Throw an exception

I'm slightly in favour of the second option. That's because the max value amounts to a wait time of a little over 24 days. If someone is prepared to wait that long for an HTTP request to complete, it is probably safe to assume that they are willing to wait forever.

Also, a comment mentioning that the cast is necessary because set_option() uses varargs would be good. (It's not obvious, unless someone studies the curl doc rather carefully.)

review: Needs Fixing
Revision history for this message
Michi Henning (michihenning) wrote :

Here is a diff that does this:

=== modified file 'src/core/net/http/impl/curl/request.h'
--- src/core/net/http/impl/curl/request.h 2014-11-13 13:16:42 +0000
+++ src/core/net/http/impl/curl/request.h 2015-01-23 05:16:35 +0000
@@ -109,7 +109,11 @@
         if (atomic_state.load() != core::net::http::Request::State::ready)
             throw core::net::http::Request::Errors::AlreadyActive{CORE_FROM_HERE()};

- easy.set_option(::curl::Option::timeout_ms, timeout.count());
+ // timeout.count() is a long long, but curl uses varargs and wants a long.
+ // If timeout.count() overflows a long, we wait forever instead of roughly 24.8 days.
+ auto count = timeout.count();
+ long adjusted_timeout = count <= std::numeric_limits<long>::max() ? count : 0;
+ easy.set_option(::curl::Option::timeout_ms, adjusted_timeout);
     }

     Response execute(const Request::ProgressHandler& ph)

45. By Marcus Tomlinson

Use std::numeric_limits<long>::max() to ensure that our cast from long long to long does not exceed the upper limit of long.

Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

> Here is a diff that does this:
>
> === modified file 'src/core/net/http/impl/curl/request.h'
> --- src/core/net/http/impl/curl/request.h 2014-11-13 13:16:42 +0000
> +++ src/core/net/http/impl/curl/request.h 2015-01-23 05:16:35 +0000
> @@ -109,7 +109,11 @@
> if (atomic_state.load() != core::net::http::Request::State::ready)
> throw
> core::net::http::Request::Errors::AlreadyActive{CORE_FROM_HERE()};
>
> - easy.set_option(::curl::Option::timeout_ms, timeout.count());
> + // timeout.count() is a long long, but curl uses varargs and wants a
> long.
> + // If timeout.count() overflows a long, we wait forever instead of
> roughly 24.8 days.
> + auto count = timeout.count();
> + long adjusted_timeout = count <= std::numeric_limits<long>::max() ?
> count : 0;
> + easy.set_option(::curl::Option::timeout_ms, adjusted_timeout);
> }
>
> Response execute(const Request::ProgressHandler& ph)

Awesome, thanks for that. Done.

Revision history for this message
Michi Henning (michihenning) wrote :

LGTM :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/core/net/http/impl/curl/request.h'
2--- src/core/net/http/impl/curl/request.h 2014-11-13 13:16:42 +0000
3+++ src/core/net/http/impl/curl/request.h 2015-01-23 06:23:52 +0000
4@@ -109,7 +109,11 @@
5 if (atomic_state.load() != core::net::http::Request::State::ready)
6 throw core::net::http::Request::Errors::AlreadyActive{CORE_FROM_HERE()};
7
8- easy.set_option(::curl::Option::timeout_ms, timeout.count());
9+ // timeout.count() is a long long, but curl uses varargs and wants a long.
10+ // If timeout.count() overflows a long, we wait forever instead of roughly 24.8 days.
11+ auto count = timeout.count();
12+ long adjusted_timeout = count <= std::numeric_limits<long>::max() ? count : 0;
13+ easy.set_option(::curl::Option::timeout_ms, adjusted_timeout);
14 }
15
16 Response execute(const Request::ProgressHandler& ph)

Subscribers

People subscribed via source and target branches