On 13/11/20 21:12 +0000, Jonathan Wakely wrote:
On 13/11/20 20:29 +0000, Mike Crowe via Libstdc++ wrote:
On Friday 13 November 2020 at 17:25:22 +0000, Jonathan Wakely wrote:
+ // Return the relative duration from (now_s + now_ns) to (abs_s + abs_ns)
+ // as a timespec.
+ struct timespec
+ relative_timespec(chrono::seconds abs_s, chrono::nanoseconds abs_ns,
+ time_t now_s, long now_ns)
+ {
+ struct timespec rt;
+
+ // Did we already time out?
+ if (now_s > abs_s.count())
+ {
+ rt.tv_sec = -1;
+ return rt;
+ }
+
+ auto rel_s = abs_s.count() - now_s;
+
+ // Avoid overflows
+ if (rel_s > __gnu_cxx::__int_traits<time_t>::__max)
+ rel_s = __gnu_cxx::__int_traits<time_t>::__max;
+ else if (rel_s < __gnu_cxx::__int_traits<time_t>::__min)
+ rel_s = __gnu_cxx::__int_traits<time_t>::__min;
I may be missing something, but if the line above executes...
+
+ // Convert the absolute timeout value to a relative timeout
+ rt.tv_sec = rel_s;
+ rt.tv_nsec = abs_ns.count() - now_ns;
+ if (rt.tv_nsec < 0)
+ {
+ rt.tv_nsec += 1000000000;
+ --rt.tv_sec;
...and so does this line above, then I think that we'll end up
underflowing. (Presumably rt.tv_sec will wrap round to being some time in
2038 on most 32-bit targets.)
Ugh.
I'm currently trying to persuade myself that this can actually happen and
if so work out how to come up with a test case for it.
Maybe something like:
auto d = chrono::floor<chrono::seconds>(system_clock::now().time_since_epoch()
- seconds(INT_MAX + 2LL));
fut.wait_until(system_clock::time_point(d));
This will create a sys_time with a value that is slightly more than
INT_MAX seconds before the current time, with a zero nanoseconds
Ah, but such a time will never reach the overflow because the first
thing that the new relative_timespec function does is:
if (now_s > abs_s.count())
{
rt.tv_sec = -1;
return rt;
}
So in fact we can never have a negative rel_s anyway.