11// Copyright 2022-2024 Protocol Labs
22// SPDX-License-Identifier: Apache-2.0, MIT
33use std:: future:: Future ;
4+ use std:: panic:: catch_unwind;
45use std:: sync:: Arc ;
6+ use futures_util:: FutureExt ;
57
68use crate :: observe:: {
79 BlockCommitted , BlockProposalEvaluated , BlockProposalReceived , BlockProposalSent , Message ,
@@ -12,7 +14,7 @@ use crate::AppExitCode;
1214use crate :: BlockHeight ;
1315use crate :: { tmconv:: * , VERSION } ;
1416use actors_custom_api:: gas_market:: Reading ;
15- use anyhow:: { anyhow, Context , Result } ;
17+ use anyhow:: { anyhow, bail , Context , Result } ;
1618use async_stm:: { atomically, atomically_or_err} ;
1719use async_trait:: async_trait;
1820use cid:: Cid ;
@@ -324,16 +326,33 @@ where
324326 guard. take ( ) . expect ( "exec state empty" )
325327 }
326328
327- /// Take the execution state, update it, put it back, return the output.
329+ /// Update the execution state using the provided closure.
330+ ///
331+ /// Note: Deals with panics in the user provided closure as well.
328332 async fn modify_exec_state < T , F , R > ( & self , f : F ) -> Result < T >
329333 where
330- F : FnOnce ( FvmExecState < BS > ) -> R ,
334+ F : FnOnce ( & mut FvmExecState < BS > ) -> R ,
331335 R : Future < Output = Result < ( FvmExecState < BS > , T ) > > ,
332336 {
333337 let mut guard = self . exec_state . lock ( ) . await ;
334338 let state = guard. take ( ) . expect ( "exec state empty" ) ;
335339
336- let ( state, ret) = f ( state) . await ?;
340+ let fut = catch_unwind ( move || { f ( state) } ) ;
341+ let fut: R = match fut {
342+ Ok ( fut) => fut,
343+ Err ( err) => {
344+ * guard = Some ( backup) ;
345+ bail ! ( "Encounterd panic in `modify_exec_state` user provided future generator invocation: {err:?}" )
346+ }
347+ } ;
348+ let res = fut. catch_unwind ( ) . await ?;
349+ let ( state, ret) : ( FvmExecState < BS > , T ) = match res {
350+ Ok ( tup) => tup,
351+ Err ( err) => {
352+ * guard = Some ( state) ;
353+ bail ! ( "Encounterd panic in `modify_exec_state` user provided future generator future polling: {err:?}" ) ;
354+ }
355+ } ;
337356
338357 * guard = Some ( state) ;
339358
0 commit comments