Integer overflow in _Jv_CondWait
Andrew Haley
aph@redhat.com
Wed Nov 23 15:33:00 GMT 2005
_Jv_CondWait makes no allowances for the possibility of an integer
overflow, and this means we can return too early.
Consider this program:
public class TimedWait
{
public static void main (String[] argv)
throws InterruptedException
{
Object o = new Object();
synchronized (o)
{
o.wait(Long.MAX_VALUE);
}
}
}
It's obvious that we never expect this program to terminate, because
the delay is some 292 million years. However, try this on gcj and it
returns immediately -- because _Jv_CondWait is broken.
We must be much more careful how we convert time from one
representation to another.
Also, there is the question of what we should do if the required
timeout won't fit into a struct timespec. In this patch I assume that
when this happens the user actually doesn't want a timeout at all.
Andrew.
2005-11-23 Andrew Haley <aph@redhat.com>
* posix-threads.cc (_Jv_CondWait): Rewrite calculation of the
struct timespec we pass to pthread_cond_timedwait.
*** posix-threads.cc~ 2005-11-09 09:48:52.000000000 +0000
--- posix-threads.cc 2005-11-23 15:28:07.000000000 +0000
***************
*** 22,25 ****
--- 22,26 ----
#include <stdlib.h>
#include <time.h>
+ #include <stdint.h>
#include <signal.h>
#include <errno.h>
***************
*** 93,104 ****
struct timespec ts;
- jlong m, startTime;
if (millis > 0 || nanos > 0)
{
! startTime = java::lang::System::currentTimeMillis();
! m = millis + startTime;
! ts.tv_sec = m / 1000;
! ts.tv_nsec = ((m % 1000) * 1000000) + nanos;
}
--- 94,118 ----
struct timespec ts;
if (millis > 0 || nanos > 0)
{
! // Calculate the abstime corresponding to the timeout.
! // Everything is in milliseconds.
! uintmax_t startTime = (uintmax_t)java::lang::System::currentTimeMillis();
! uintmax_t m = (uintmax_t)millis + startTime;
! uintmax_t seconds = m / 1000;
!
! ts.tv_sec = seconds;
! if (ts.tv_sec < 0 || ts.tv_sec != seconds)
! {
! // We treat a timeout that won't fit into a struct timespec
! // as a wait forever.
! millis = nanos = 0;
! }
! else
! {
! m = m - seconds * 1000;
! ts.tv_nsec = m * 1000000 + (uintmax_t)nanos;
! }
}
More information about the Java-patches
mailing list