@@ -11,6 +11,7 @@ use std::{
1111 path:: PathBuf ,
1212 process:: ExitCode ,
1313 sync:: { Arc , Mutex } ,
14+ time:: { Duration , Instant } ,
1415} ;
1516
1617use crate :: {
@@ -29,7 +30,7 @@ use intrinsic::{annotations::init_calculi, distributions::init_distributions, li
2930use mc:: run_storm:: { run_storm, storm_result_to_diagnostic} ;
3031use proof_rules:: init_encodings;
3132use regex:: Regex ;
32- use resource_limits:: { await_with_resource_limits, LimitError , LimitsRef } ;
33+ use resource_limits:: { await_with_resource_limits, LimitError , LimitsRef , MemorySize } ;
3334use servers:: { run_lsp_server, CliServer , LspServer , Server , ServerError } ;
3435use slicing:: init_slicing;
3536use thiserror:: Error ;
@@ -183,7 +184,17 @@ pub struct ResourceLimitOptions {
183184
184185 /// Memory usage limit in megabytes.
185186 #[ arg( long = "mem" , default_value = "8192" ) ]
186- pub mem_limit : u64 ,
187+ pub mem_limit : usize ,
188+ }
189+
190+ impl ResourceLimitOptions {
191+ fn timeout ( & self ) -> Duration {
192+ Duration :: from_secs ( self . timeout )
193+ }
194+
195+ fn mem_limit ( & self ) -> MemorySize {
196+ MemorySize :: megabytes ( self . mem_limit )
197+ }
187198}
188199
189200#[ derive( Debug , Clone , Copy , PartialEq , Eq , ValueEnum ) ]
@@ -239,6 +250,19 @@ pub struct JaniOptions {
239250 /// for constants in the model.
240251 #[ arg( long) ]
241252 pub storm_constants : Option < String > ,
253+
254+ /// Timeout in seconds for running Storm.
255+ ///
256+ /// Caesar uses the minimum of this value and the remaining time from the
257+ /// `--timeout` option.
258+ #[ arg( long) ]
259+ pub storm_timeout : Option < u64 > ,
260+ }
261+
262+ impl JaniOptions {
263+ pub fn storm_timeout ( & self ) -> Option < Duration > {
264+ self . storm_timeout . map ( Duration :: from_secs)
265+ }
242266}
243267
244268#[ derive( Debug , Default , Args ) ]
@@ -454,7 +478,7 @@ fn finalize_verify_result(
454478 rlimit_options : & ResourceLimitOptions ,
455479 verify_result : Result < bool , VerifyError > ,
456480) -> ExitCode {
457- let ( timeout, mem_limit) = ( rlimit_options. timeout , rlimit_options. mem_limit ) ;
481+ let ( timeout, mem_limit) = ( rlimit_options. timeout ( ) , rlimit_options. mem_limit ( ) ) ;
458482 match verify_result {
459483 #[ allow( clippy:: bool_to_int_with_if) ]
460484 Ok ( all_verified) => ExitCode :: from ( if all_verified { 0 } else { 1 } ) ,
@@ -467,11 +491,14 @@ fn finalize_verify_result(
467491 ExitCode :: from ( 1 )
468492 }
469493 Err ( VerifyError :: LimitError ( LimitError :: Timeout ) ) => {
470- tracing:: error!( "Timed out after {} seconds, exiting." , timeout) ;
494+ tracing:: error!( "Timed out after {} seconds, exiting." , timeout. as_secs ( ) ) ;
471495 std:: process:: exit ( 2 ) ; // exit ASAP
472496 }
473497 Err ( VerifyError :: LimitError ( LimitError :: Oom ) ) => {
474- tracing:: error!( "Exhausted {} megabytes of memory, exiting." , mem_limit) ;
498+ tracing:: error!(
499+ "Exhausted {} megabytes of memory, exiting." ,
500+ mem_limit. as_megabytes( )
501+ ) ;
475502 std:: process:: exit ( 3 ) ; // exit ASAP
476503 }
477504 Err ( VerifyError :: UserError ( err) ) => {
@@ -587,8 +614,8 @@ pub async fn verify_files(
587614 } ;
588615 // Unpacking lots of Results with `.await??` :-)
589616 await_with_resource_limits (
590- Some ( options. rlimit_options . timeout ) ,
591- Some ( options. rlimit_options . mem_limit ) ,
617+ Some ( options. rlimit_options . timeout ( ) ) ,
618+ Some ( options. rlimit_options . mem_limit ( ) ) ,
592619 handle,
593620 )
594621 . await ??
@@ -671,7 +698,7 @@ pub(crate) fn verify_test(source: &str) -> (Result<bool, VerifyError>, servers::
671698 . id ;
672699
673700 let options = Arc :: new ( options) ;
674- let limits_ref = LimitsRef :: new ( None ) ;
701+ let limits_ref = LimitsRef :: new ( None , None ) ;
675702 let res = verify_files_main ( & options, limits_ref, & mut server, & [ file_id] ) ;
676703 ( res, server)
677704}
@@ -756,6 +783,7 @@ fn verify_files_main(
756783 & options. jani_options ,
757784 & mut source_units,
758785 server,
786+ & limits_ref,
759787 & tcx,
760788 false ,
761789 ) ?;
@@ -942,10 +970,14 @@ fn to_jani_loader(
942970 & mut * server_lock,
943971 & user_files,
944972 ) ?;
973+ let timeout = Instant :: now ( ) + options. rlimit_options . timeout ( ) ;
974+ let mem_limit = options. rlimit_options . mem_limit ( ) ;
975+ let limits_ref = LimitsRef :: new ( Some ( timeout) , Some ( mem_limit) ) ;
945976 to_jani_main (
946977 & options. jani_options ,
947978 & mut source_units,
948979 server_lock. deref_mut ( ) ,
980+ & limits_ref,
949981 & tcx,
950982 true ,
951983 )
@@ -955,6 +987,7 @@ fn to_jani_main(
955987 options : & JaniOptions ,
956988 source_units : & mut Vec < Item < SourceUnit > > ,
957989 server : & mut dyn Server ,
990+ limits_ref : & LimitsRef ,
958991 tcx : & TyCtx ,
959992 is_jani_command : bool ,
960993) -> Result < ( ) , VerifyError > {
@@ -985,8 +1018,8 @@ fn to_jani_main(
9851018 Err ( err) => Err ( err) ?,
9861019 Ok ( Some ( path) ) => {
9871020 tracing:: debug!( file=?path. display( ) , "wrote JANI file" ) ;
988- if let Some ( which_storm ) = options. run_storm {
989- let res = run_storm ( & options, which_storm , & path, vec ! [ "reward" . to_owned( ) ] ) ;
1021+ if options. run_storm . is_some ( ) {
1022+ let res = run_storm ( & options, & path, vec ! [ "reward" . to_owned( ) ] , limits_ref ) ;
9901023 server. add_diagnostic ( storm_result_to_diagnostic (
9911024 & res,
9921025 source_unit. diagnostic_span ( ) ,
0 commit comments