mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-21 15:19:53 +01:00
Return early if LifecycleManager#stopServices() is called twice.
This could happen if the app shuts down spontaneously (eg due to low memory) concurrently with a manual shutdown.
This commit is contained in:
@@ -190,6 +190,10 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
if (state == STOPPING) {
|
||||||
|
LOG.info("Already stopped");
|
||||||
|
return;
|
||||||
|
}
|
||||||
LOG.info("Stopping services");
|
LOG.info("Stopping services");
|
||||||
state = STOPPING;
|
state = STOPPING;
|
||||||
eventBus.broadcast(new LifecycleEvent(STOPPING));
|
eventBus.broadcast(new LifecycleEvent(STOPPING));
|
||||||
|
|||||||
@@ -9,12 +9,16 @@ import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
|
|||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
import org.briarproject.bramble.test.DbExpectations;
|
import org.briarproject.bramble.test.DbExpectations;
|
||||||
|
import org.jmock.Expectations;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertTrue;
|
import static junit.framework.TestCase.assertTrue;
|
||||||
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
|
||||||
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING;
|
||||||
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.CLOCK_ERROR;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.CLOCK_ERROR;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
|
||||||
import static org.briarproject.bramble.api.system.Clock.MAX_REASONABLE_TIME_MS;
|
import static org.briarproject.bramble.api.system.Clock.MAX_REASONABLE_TIME_MS;
|
||||||
@@ -57,6 +61,7 @@ public class LifecycleManagerImplTest extends BrambleMockTestCase {
|
|||||||
lifecycleManager.registerOpenDatabaseHook(hook);
|
lifecycleManager.registerOpenDatabaseHook(hook);
|
||||||
|
|
||||||
assertEquals(SUCCESS, lifecycleManager.startServices(dbKey));
|
assertEquals(SUCCESS, lifecycleManager.startServices(dbKey));
|
||||||
|
assertEquals(RUNNING, lifecycleManager.getLifecycleState());
|
||||||
assertTrue(called.get());
|
assertTrue(called.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +74,7 @@ public class LifecycleManagerImplTest extends BrambleMockTestCase {
|
|||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(CLOCK_ERROR, lifecycleManager.startServices(dbKey));
|
assertEquals(CLOCK_ERROR, lifecycleManager.startServices(dbKey));
|
||||||
|
assertEquals(STARTING, lifecycleManager.getLifecycleState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -80,5 +86,40 @@ public class LifecycleManagerImplTest extends BrambleMockTestCase {
|
|||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(CLOCK_ERROR, lifecycleManager.startServices(dbKey));
|
assertEquals(CLOCK_ERROR, lifecycleManager.startServices(dbKey));
|
||||||
|
assertEquals(STARTING, lifecycleManager.getLifecycleState());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSecondCallToStopServicesReturnsEarly() throws Exception {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
|
context.checking(new DbExpectations() {{
|
||||||
|
oneOf(clock).currentTimeMillis();
|
||||||
|
will(returnValue(now));
|
||||||
|
oneOf(db).open(dbKey, lifecycleManager);
|
||||||
|
will(returnValue(false));
|
||||||
|
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||||
|
oneOf(db).removeTemporaryMessages(txn);
|
||||||
|
exactly(2).of(eventBus).broadcast(with(any(LifecycleEvent.class)));
|
||||||
|
}});
|
||||||
|
|
||||||
|
assertEquals(SUCCESS, lifecycleManager.startServices(dbKey));
|
||||||
|
assertEquals(RUNNING, lifecycleManager.getLifecycleState());
|
||||||
|
context.assertIsSatisfied();
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(eventBus).broadcast(with(any(LifecycleEvent.class)));
|
||||||
|
oneOf(db).close();
|
||||||
|
}});
|
||||||
|
|
||||||
|
lifecycleManager.stopServices();
|
||||||
|
assertEquals(STOPPING, lifecycleManager.getLifecycleState());
|
||||||
|
context.assertIsSatisfied();
|
||||||
|
|
||||||
|
// Calling stopServices() again should not broadcast another event or
|
||||||
|
// try to close the DB again
|
||||||
|
lifecycleManager.stopServices();
|
||||||
|
assertEquals(STOPPING, lifecycleManager.getLifecycleState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user