@@ -1028,6 +1028,14 @@ impl<A: Actor> Instance<A> {
10281028 self . status_tx . send_replace ( new. clone ( ) ) ;
10291029 }
10301030
1031+ fn is_terminal ( & self ) -> bool {
1032+ self . status_tx . borrow ( ) . is_terminal ( )
1033+ }
1034+
1035+ fn is_stopped ( & self ) -> bool {
1036+ self . status_tx . borrow ( ) . is_stopped ( )
1037+ }
1038+
10311039 /// This instance's actor ID.
10321040 pub fn self_id ( & self ) -> & ActorId {
10331041 self . mailbox . actor_id ( )
@@ -1119,23 +1127,35 @@ impl<A: Actor> Instance<A> {
11191127 . run_actor_tree ( & mut actor, actor_loop_receivers, & mut work_rx)
11201128 . await ;
11211129
1122- let ( actor_status , event) = match result {
1123- Ok ( _) => ( ActorStatus :: Stopped , None ) ,
1124- Err ( ActorError {
1125- kind : box ActorErrorKind :: UnhandledSupervisionEvent ( box event ) ,
1126- ..
1127- } ) => ( event . actor_status . clone ( ) , Some ( event ) ) ,
1130+ let event = match result {
1131+ Ok ( _) => {
1132+ // actor should have been stopped by run_actor_tree
1133+ assert ! ( self . is_stopped ( ) ) ;
1134+ None
1135+ }
11281136 Err ( err) => {
1129- let error_kind = ActorErrorKind :: Generic ( err. kind . to_string ( ) ) ;
1130- (
1131- ActorStatus :: Failed ( error_kind. clone ( ) ) ,
1132- Some ( ActorSupervisionEvent :: new (
1133- self . cell . actor_id ( ) . clone ( ) ,
1134- ActorStatus :: Failed ( error_kind) ,
1135- None ,
1136- None ,
1137- ) ) ,
1138- )
1137+ assert ! ( !self . is_terminal( ) ) ;
1138+ match * err. kind {
1139+ ActorErrorKind :: UnhandledSupervisionEvent ( box event) => {
1140+ // Currently only terminated actors are allowed to raise supervision events.
1141+ // If we want to change that in the future, we need to modify the exit
1142+ // status here too, because we use event's actor_status as this actor's
1143+ // terminal status.
1144+ assert ! ( event. actor_status. is_terminal( ) ) ;
1145+ self . change_status ( event. actor_status . clone ( ) ) ;
1146+ Some ( event)
1147+ }
1148+ _ => {
1149+ let error_kind = ActorErrorKind :: Generic ( err. kind . to_string ( ) ) ;
1150+ self . change_status ( ActorStatus :: Failed ( error_kind. clone ( ) ) ) ;
1151+ Some ( ActorSupervisionEvent :: new (
1152+ self . cell . actor_id ( ) . clone ( ) ,
1153+ ActorStatus :: Failed ( error_kind) ,
1154+ None ,
1155+ None ,
1156+ ) )
1157+ }
1158+ }
11391159 }
11401160 } ;
11411161
@@ -1164,7 +1184,6 @@ impl<A: Actor> Instance<A> {
11641184 self . proc . handle_supervision_event ( event) ;
11651185 }
11661186 }
1167- self . change_status ( actor_status) ;
11681187 }
11691188
11701189 /// Runs the actor, and manages its supervision tree. When the function returns,
@@ -1207,10 +1226,16 @@ impl<A: Actor> Instance<A> {
12071226 }
12081227 } ;
12091228
1210- if let Err ( ref err) = result {
1211- tracing:: error!( "{}: actor failure: {}" , self . self_id( ) , err) ;
1229+ match & result {
1230+ Ok ( _) => assert ! ( self . is_stopped( ) ) ,
1231+ Err ( err) => {
1232+ tracing:: error!( "{}: actor failure: {}" , self . self_id( ) , err) ;
1233+ assert ! ( !self . is_terminal( ) ) ;
1234+ // Send Stopping instead of Failed, because we still need to
1235+ // unlink child actors.
1236+ self . change_status ( ActorStatus :: Stopping ) ;
1237+ }
12121238 }
1213- self . change_status ( ActorStatus :: Stopping ) ;
12141239
12151240 // After this point, we know we won't spawn any more children,
12161241 // so we can safely read the current child keys.
0 commit comments