You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@etch.apache.org by sc...@apache.org on 2008/12/01 23:15:09 UTC

svn commit: r722262 - in /incubator/etch/trunk/util/src: main/java/etch/util/AbstractStartable.java main/java/etch/util/AlarmManager.java test/java/etch/util/TestAlarmManager.java

Author: sccomer
Date: Mon Dec  1 14:15:09 2008
New Revision: 722262

URL: http://svn.apache.org/viewvc?rev=722262&view=rev
Log:
java fix for ETCH-11: AlarmManager deadlocks during shutdown().

AlarmManager.shutdown() just calls AbstractStartable.stop() on the static instance.
the bug was actually in AbstractStartable.stop().
created unit test for AlarmManager which covers this case.

Added:
    incubator/etch/trunk/util/src/test/java/etch/util/TestAlarmManager.java   (with props)
Modified:
    incubator/etch/trunk/util/src/main/java/etch/util/AbstractStartable.java
    incubator/etch/trunk/util/src/main/java/etch/util/AlarmManager.java

Modified: incubator/etch/trunk/util/src/main/java/etch/util/AbstractStartable.java
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/util/src/main/java/etch/util/AbstractStartable.java?rev=722262&r1=722261&r2=722262&view=diff
==============================================================================
--- incubator/etch/trunk/util/src/main/java/etch/util/AbstractStartable.java (original)
+++ incubator/etch/trunk/util/src/main/java/etch/util/AbstractStartable.java Mon Dec  1 14:15:09 2008
@@ -22,28 +22,34 @@
  */
 abstract public class AbstractStartable implements Startable
 {
-	final public synchronized void start() throws Exception
+	final public void start() throws Exception
 	{
-		if (isStarted())
-			throw new IllegalStateException( "is already started" );
+		synchronized (this)
+		{
+			if (isStarted())
+				throw new IllegalStateException( "is already started" );
+
+			started = true;
+		}
 		
 		try
 		{
-			started = true;
 			start0();
 		}
 		catch ( Exception e )
 		{
-			setStopped();
-			stop0();
+			stop();
 			throw e;
 		}
 	}
 
-	final public synchronized void stop() throws Exception
+	final public void stop() throws Exception
 	{
-		checkIsStarted();
-		setStopped();
+		synchronized (this)
+		{
+			checkIsStarted();
+			setStopped();
+		}
 		stop0();
 	}
 	

Modified: incubator/etch/trunk/util/src/main/java/etch/util/AlarmManager.java
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/util/src/main/java/etch/util/AlarmManager.java?rev=722262&r1=722261&r2=722262&view=diff
==============================================================================
--- incubator/etch/trunk/util/src/main/java/etch/util/AlarmManager.java (original)
+++ incubator/etch/trunk/util/src/main/java/etch/util/AlarmManager.java Mon Dec  1 14:15:09 2008
@@ -180,7 +180,11 @@
 	{
 		clearAlarms();
 		clearQueue();
-		notifyAll();
+		
+		synchronized (this)
+		{
+			notifyAll();
+		}
 		
 		for (int i = 0; i < nWorkers; i++)
 		{

Added: incubator/etch/trunk/util/src/test/java/etch/util/TestAlarmManager.java
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/util/src/test/java/etch/util/TestAlarmManager.java?rev=722262&view=auto
==============================================================================
--- incubator/etch/trunk/util/src/test/java/etch/util/TestAlarmManager.java (added)
+++ incubator/etch/trunk/util/src/test/java/etch/util/TestAlarmManager.java Mon Dec  1 14:15:09 2008
@@ -0,0 +1,113 @@
+/*
+ * $Id$
+ * 
+ * Copyright 2007-2008 Cisco Systems Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package etch.util;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/** Test of AlarmManager */
+public class TestAlarmManager
+{
+	private final static int Q1 = 30;
+	private final static int Q2 = 60;
+	
+	/** @throws Exception */
+	@Test( expected = IllegalStateException.class )
+	public void start1() throws Exception
+	{
+		// is not started
+		AlarmManager am = new AlarmManager();
+		
+		MyAlarmListener listener = new MyAlarmListener( 0 );
+		assertEquals( 0, listener.delay );
+		assertFalse( listener.wake );
+		assertNull( listener.state );
+		
+		am.add( listener, null, Q1 );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void start2() throws Exception
+	{
+		// is not started
+		AlarmManager am = new AlarmManager();
+		
+		MyAlarmListener listener = new MyAlarmListener( 0 );
+		assertEquals( 0, listener.delay );
+		assertFalse( listener.wake );
+		assertNull( listener.state );
+		
+		am.start();
+		
+		am.add( listener, null, Q1 );
+		assertFalse( listener.wake );
+		assertNull( listener.state );
+		
+		Thread.sleep( Q2 );
+		assertTrue( listener.wake );
+		assertNull( listener.state );
+	}
+	
+	/** @throws Exception */
+	@Test
+	public void start3() throws Exception
+	{
+		// is not started
+		AlarmManager am = new AlarmManager();
+		
+		MyAlarmListener listener = new MyAlarmListener( 0 );
+		assertEquals( 0, listener.delay );
+		assertFalse( listener.wake );
+		assertNull( listener.state );
+		
+		am.start();
+		
+		am.add( listener, null, Q1 );
+		assertFalse( listener.wake );
+		assertNull( listener.state );
+		
+		Thread.sleep( Q2 );
+		assertTrue( listener.wake );
+		assertNull( listener.state );
+		
+		am.stop();
+	}
+
+	private static class MyAlarmListener implements AlarmListener
+	{
+		public MyAlarmListener( int delay )
+		{
+			this.delay = delay;
+		}
+
+		private int delay;
+		
+		private boolean wake;
+		
+		private Object state;
+		
+		public int wakeup( AlarmManager manager, Object state, long due )
+		{
+			wake = true;
+			this.state = state;
+			return delay;
+		}
+	}
+}

Propchange: incubator/etch/trunk/util/src/test/java/etch/util/TestAlarmManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/etch/trunk/util/src/test/java/etch/util/TestAlarmManager.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"