From bab18af92cdcbc0405381cac673a42bef3c1702e Mon Sep 17 00:00:00 2001 From: Roland Date: Fri, 4 May 2012 22:30:00 +0200 Subject: [PATCH] fix bug in FSM when manually rescheduling non-recurring timer, see #2043 cherry-picked from 0314b9abbbeac4a0c8f72dea6fb866eb29cb3847 plus test case written --- .../test/scala/akka/actor/FSMTimingSpec.scala | 24 +++++++++++++++++-- .../src/main/scala/akka/actor/FSM.scala | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/akka-actor-tests/src/test/scala/akka/actor/FSMTimingSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/FSMTimingSpec.scala index 59468125eb..df47c801bb 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/FSMTimingSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/FSMTimingSpec.scala @@ -67,6 +67,18 @@ class FSMTimingSpec extends AkkaSpec with ImplicitSender { } } + "resubmit single-shot timer" taggedAs TimingTest in { + within(2 seconds) { + within(500 millis, 1.5 second) { + fsm ! TestSingleTimerResubmit + expectMsg(Tick) + expectMsg(Tock) + expectMsg(Transition(fsm, TestSingleTimerResubmit, Initial)) + } + expectNoMsg + } + } + "correctly cancel a named timer" taggedAs TimingTest in { fsm ! TestCancelTimer within(500 millis) { @@ -106,8 +118,8 @@ class FSMTimingSpec extends AkkaSpec with ImplicitSender { } "notify unhandled messages" taggedAs TimingTest in { - filterEvents(EventFilter.warning("unhandled event Tick in state TestUnhandled", source = fsm.toString, occurrences = 1), - EventFilter.warning("unhandled event Unhandled(test) in state TestUnhandled", source = fsm.toString, occurrences = 1)) { + filterEvents(EventFilter.warning("unhandled event Tick in state TestUnhandled", source = fsm.path.toString, occurrences = 1), + EventFilter.warning("unhandled event Unhandled(test) in state TestUnhandled", source = fsm.path.toString, occurrences = 1)) { fsm ! TestUnhandled within(1 second) { fsm ! Tick @@ -142,6 +154,7 @@ object FSMTimingSpec { case object TestStateTimeout extends State case object TestStateTimeoutOverride extends State case object TestSingleTimer extends State + case object TestSingleTimerResubmit extends State case object TestRepeatedTimer extends State case object TestUnhandled extends State case object TestCancelTimer extends State @@ -179,6 +192,13 @@ object FSMTimingSpec { tester ! Tick goto(Initial) } + onTransition { + case Initial -> TestSingleTimerResubmit ⇒ setTimer("blah", Tick, 500 millis, false) + } + when(TestSingleTimerResubmit) { + case Event(Tick, _) ⇒ tester ! Tick; setTimer("blah", Tock, 500 millis, false) + case Event(Tock, _) ⇒ tester ! Tock; goto(Initial) + } when(TestCancelTimer) { case Event(Tick, _) ⇒ setTimer("hallo", Tock, 1 milli, false) diff --git a/akka-actor/src/main/scala/akka/actor/FSM.scala b/akka-actor/src/main/scala/akka/actor/FSM.scala index b277142e76..81126c4d8d 100644 --- a/akka-actor/src/main/scala/akka/actor/FSM.scala +++ b/akka-actor/src/main/scala/akka/actor/FSM.scala @@ -443,10 +443,10 @@ trait FSM[S, D] extends Listeners { timeoutFuture = None } generation += 1 - processMsg(msg, t) if (!repeat) { timers -= name } + processMsg(msg, t) } case SubscribeTransitionCallBack(actorRef) ⇒ // TODO use DeathWatch to clean up list