The value for “now” needs to be reestablished in the loop, or else this loop will wait too long on a spurious wake up.
Gregg On Dec 23, 2013, at 5:52 AM, peter_firmst...@apache.org wrote: > Author: peter_firmstone > Date: Mon Dec 23 11:52:40 2013 > New Revision: 1553097 > > URL: http://svn.apache.org/r1553097 > Log: > After considerable testing using a multi threaded Executor and Runnable tasks > to CAS an AtomicLong to generate 100% cpu load, no data races were found, it > is suspected that Object.wait is subject to spurious wake-up's on some > platforms when they are not contained within a loop that checks the present > condition and this is causing the test failures: > > > > > Modified: > > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/QAConfig.java > > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/LeaseExpirationTest.java > > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/notify/ThrowRuntimeException.java > > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/BaseQATest.java > > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/ClientFlowControlTest.java > > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/CloseTest.java > > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/MuxClientTest.java > > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/renewalmanager/EventTest.java > > river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/AbstractLookupDiscovery.java > > Modified: > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/QAConfig.java > URL: > http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/QAConfig.java?rev=1553097&r1=1553096&r2=1553097&view=diff > ============================================================================== > --- > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/QAConfig.java > (original) > +++ > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/QAConfig.java > Mon Dec 23 11:52:40 2013 > @@ -2213,7 +2213,7 @@ public class QAConfig implements Seriali > if (fqHostName.contains(nxdomain)) return hostName; > return fqHostName; > } catch (UnknownHostException ignore) { > - logger.severe("InetAddress threw unknown host exception: " + > hostName); > + logger.info("InetAddress threw unknown host exception: " + > hostName); > } > return hostName; > } > > Modified: > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/LeaseExpirationTest.java > URL: > http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/LeaseExpirationTest.java?rev=1553097&r1=1553096&r2=1553097&view=diff > ============================================================================== > --- > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/LeaseExpirationTest.java > (original) > +++ > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/LeaseExpirationTest.java > Mon Dec 23 11:52:40 2013 > @@ -360,12 +360,13 @@ public class LeaseExpirationTest extends > if (count != 0) > return false; > > - final long now = System.currentTimeMillis(); > + long now = System.currentTimeMillis(); > synchronized (this) { > - if (setExpiration > now) { > + while (setExpiration > now) { > logger.log(Level.INFO, "Waiting for " + (setExpiration - > now) > + " ms for set lease to expire"); > wait(setExpiration - now); > + now = System.currentTimeMillis(); > } > } > return true; > > Modified: > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/notify/ThrowRuntimeException.java > URL: > http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/notify/ThrowRuntimeException.java?rev=1553097&r1=1553096&r2=1553097&view=diff > ============================================================================== > --- > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/notify/ThrowRuntimeException.java > (original) > +++ > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/notify/ThrowRuntimeException.java > Mon Dec 23 11:52:40 2013 > @@ -196,14 +196,16 @@ public class ThrowRuntimeException exten > */ > long listener1Rcvd; > synchronized (listener1) { > - > + long duration = wait; > + long finish = System.currentTimeMillis() + duration; > + > // Did it already happen? > listener1Rcvd = listener1.lastEvent(); > > - if (listener1Rcvd < ev1) { > + while (listener1Rcvd < ev1) { > > // No, wait > - listener1.wait(wait); > + listener1.wait(duration); > listener1Rcvd = listener1.lastEvent(); > > if (listener1Rcvd < 0) { > @@ -214,6 +216,8 @@ public class ThrowRuntimeException exten > "First listener received too many events"); > } > logger.log(Level.INFO, "Received correct event"); > + duration = finish - System.currentTimeMillis(); > + if (duration <= 0) break; > } > } > > @@ -254,12 +258,14 @@ public class ThrowRuntimeException exten > > // Wait for event and check to see if it is the right one > synchronized (listener2) { > - > + long duration = wait; > + long finish = System.currentTimeMillis() + duration; > + > // Did it already happen? > - if (listener2.lastEvent() < ev1) { > + while (listener2.lastEvent() < ev1) { > > // No wait > - listener2.wait(wait); > + listener2.wait(duration); > > if (listener2.lastEvent() < 0) { > throw new TestException( > @@ -268,6 +274,8 @@ public class ThrowRuntimeException exten > throw new TestException( > "Second listener received too many events"); > } > + duration = finish - System.currentTimeMillis(); > + if (duration <= 0) break; > } > } > logger.log(Level.INFO, "2nd handler received correct event"); > > Modified: > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/BaseQATest.java > URL: > http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/BaseQATest.java?rev=1553097&r1=1553096&r2=1553097&view=diff > ============================================================================== > --- > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/BaseQATest.java > (original) > +++ > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/BaseQATest.java > Mon Dec 23 11:52:40 2013 > @@ -1638,7 +1638,13 @@ abstract public class BaseQATest extends > }//endif > }//endif(nEventsReceived == nEventsExpected) > try { > - listener.wait(1000); // Wait for discovery for up to > 1000 ms. > + long startTime = System.currentTimeMillis(); > + long finishTime = startTime + 1000; > + long remain = 1000; > + do { > + listener.wait(remain); // Wait for discovery for > 1000 ms. > + remain = finishTime - System.currentTimeMillis(); > + } while (remain > 0); //To avoid spurious wakeup > } catch (InterruptedException ex) { > throw new TestException("Interrupted while waiting for > discovery", ex); > } > @@ -1794,7 +1800,13 @@ abstract public class BaseQATest extends > }//endif > }//endif(nEventsReceived == nEventsExpected) > try { > - listener.wait(1000); > + long startTime = System.currentTimeMillis(); > + long finishTime = startTime + 1000; > + long remain = 1000; > + do { > + listener.wait(remain); // Wait for discovery for > 1000 ms. > + remain = finishTime - System.currentTimeMillis(); > + } while (remain > 0); //To avoid spurious wakeup > } catch (InterruptedException ex) { > throw new TestException("Test interrupted while waiting > for discard", ex); > } > @@ -1948,10 +1960,17 @@ abstract public class BaseQATest extends > }//endif > }//endif(nEventsReceived == nEventsExpected) > try { > - listener.wait(1000); > + long startTime = System.currentTimeMillis(); > + long finishTime = startTime + 1000; > + long remain = 1000; > + do { > + listener.wait(remain); // Wait for discovery for > 1000 ms. > + remain = finishTime - System.currentTimeMillis(); > + } while (remain > 0); //To avoid spurious wakeup > } catch (InterruptedException ex) { > throw new TestException("Test interrupted while waiting > for change event", ex); > } > + // can't do this anymore because we need to release sync > first. > //DiscoveryServiceUtil.delayMS(1000); > showCompInfo = false;//display comparison info only when i = 0 > }//end loop(iLoop) > > Modified: > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/ClientFlowControlTest.java > URL: > http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/ClientFlowControlTest.java?rev=1553097&r1=1553096&r2=1553097&view=diff > ============================================================================== > --- > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/ClientFlowControlTest.java > (original) > +++ > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/ClientFlowControlTest.java > Mon Dec 23 11:52:40 2013 > @@ -171,7 +171,12 @@ public class ClientFlowControlTest exten > private Socket getConnection() throws InterruptedException { > if (s==null) { > synchronized (lock) { > - lock.wait(2 * getTimeout()); > + long duration = 2 * getTimeout(); > + long finish = System.currentTimeMillis() + duration; > + do { > + lock.wait(duration); > + duration = finish - System.currentTimeMillis(); > + } while ( s == null && duration > 0); > } > } > Socket temp = s; > > Modified: > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/CloseTest.java > URL: > http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/CloseTest.java?rev=1553097&r1=1553096&r2=1553097&view=diff > ============================================================================== > --- > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/CloseTest.java > (original) > +++ > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/CloseTest.java > Mon Dec 23 11:52:40 2013 > @@ -158,7 +158,12 @@ public class CloseTest extends AbstractM > private Socket getConnection() throws InterruptedException { > if (s==null) { > synchronized (lock) { > - lock.wait(2 * getTimeout()); > + long duration = 2 * getTimeout(); > + long finish = System.currentTimeMillis() + duration; > + do { > + lock.wait(duration); > + duration = finish - System.currentTimeMillis(); > + } while ( s == null && duration > 0); > } > } > Socket temp = s; > > Modified: > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/MuxClientTest.java > URL: > http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/MuxClientTest.java?rev=1553097&r1=1553096&r2=1553097&view=diff > ============================================================================== > --- > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/MuxClientTest.java > (original) > +++ > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/jeri/mux/MuxClientTest.java > Mon Dec 23 11:52:40 2013 > @@ -218,7 +218,12 @@ public class MuxClientTest extends Abstr > private Socket getConnection() throws InterruptedException { > if (s==null) { > synchronized (lock) { > - lock.wait(2 * getTimeout()); > + long duration = 2 * getTimeout(); > + long finish = System.currentTimeMillis() + duration; > + do { > + lock.wait(duration); > + duration = finish - System.currentTimeMillis(); > + } while ( s == null && duration > 0); > } > } > Socket temp = s; > > Modified: > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/renewalmanager/EventTest.java > URL: > http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/renewalmanager/EventTest.java?rev=1553097&r1=1553096&r2=1553097&view=diff > ============================================================================== > --- > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/renewalmanager/EventTest.java > (original) > +++ > river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/spec/renewalmanager/EventTest.java > Mon Dec 23 11:52:40 2013 > @@ -356,7 +356,11 @@ public class EventTest extends QATestEnv > synchronized (this) { > if (null == (failedComponet = hadEarlyFailure(leases))) { > // let run() propogate InterruptedException > - wait(waitUntil - System.currentTimeMillis()); > + long duration = waitUntil - System.currentTimeMillis(); > + do { > + wait(duration); > + duration = waitUntil - System.currentTimeMillis(); > + } while (duration > 0); > failedComponet = hadEarlyFailure(leases); > } > } > > Modified: > river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/AbstractLookupDiscovery.java > URL: > http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/AbstractLookupDiscovery.java?rev=1553097&r1=1553096&r2=1553097&view=diff > ============================================================================== > --- > river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/AbstractLookupDiscovery.java > (original) > +++ > river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/AbstractLookupDiscovery.java > Mon Dec 23 11:52:40 2013 > @@ -816,11 +816,12 @@ abstract class AbstractLookupDiscovery i > sleep(multicastAnnouncementInterval); > long curTime = System.currentTimeMillis(); > synchronized (registrars) { > - /* can't modify regInfo while iterating over it, > - * so clone it > + /* Previously regInfo was cloned to avoid > synchronizing > + * this was changed to a simple synchronized block > during code > + * auditing as it appeared like an unnecessary > + * performance optimisation that risked atomicity. > */ > - HashMap<ServiceID,AnnouncementInfo> regInfoClone = > (HashMap<ServiceID,AnnouncementInfo>) regInfo.clone(); > - Set<Map.Entry<ServiceID,AnnouncementInfo>> eSet = > regInfoClone.entrySet(); > + Set<Map.Entry<ServiceID,AnnouncementInfo>> eSet = > regInfo.entrySet(); > for(Iterator<Map.Entry<ServiceID,AnnouncementInfo>> > itr = eSet.iterator(); itr.hasNext(); ) { > Map.Entry<ServiceID,AnnouncementInfo> pair = > itr.next(); > ServiceID srvcID = pair.getKey(); > >