From efda8d0aa015b7bb923b9142fcf43327e8794b4d Mon Sep 17 00:00:00 2001 From: meship-starkware Date: Thu, 7 Nov 2024 16:25:55 +0200 Subject: [PATCH] chore: check if a thread is still alive after the block is dead --- .../src/py_block_executor.rs | 66 ++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/crates/native_blockifier/src/py_block_executor.rs b/crates/native_blockifier/src/py_block_executor.rs index 7bf28040a1..b0ed044149 100644 --- a/crates/native_blockifier/src/py_block_executor.rs +++ b/crates/native_blockifier/src/py_block_executor.rs @@ -33,6 +33,8 @@ use crate::storage::{PapyrusStorage, Storage, StorageConfig}; pub(crate) type RawTransactionExecutionResult = Vec; pub(crate) type PyVisitedSegmentsMapping = Vec<(PyFelt, Vec)>; +use std::sync::{Arc, Mutex}; +use std::thread::{self, JoinHandle}; #[cfg(test)] #[path = "py_block_executor_test.rs"] mod py_block_executor_test; @@ -113,7 +115,10 @@ impl ThinTransactionExecutionInfo { ResourcesMapping(resources) } } - +struct MyStruct { + a: i32, + b: i32, +} #[pyclass] pub struct PyBlockExecutor { pub bouncer_config: BouncerConfig, @@ -124,6 +129,8 @@ pub struct PyBlockExecutor { /// `Send` trait is required for `pyclass` compatibility as Python objects must be threadsafe. pub storage: Box, pub global_contract_cache: GlobalContractCache, + thread_handle: Arc>>>, + shared_struct: Arc>>, } #[pymethods] @@ -145,6 +152,16 @@ impl PyBlockExecutor { VersionedConstants::get_versioned_constants(py_versioned_constants_overrides.into()); log::debug!("Initialized Block Executor."); + let shared_struct = Arc::new(Mutex::new(None)); + let shared_struct_clone = Arc::clone(&shared_struct); + let thread_handle = Arc::new(Mutex::new(Some(thread::spawn(move || { + loop { + let mut shared_struct = shared_struct_clone.lock().unwrap(); + *shared_struct = Some(MyStruct { a: 1, b: 2 }); + thread::sleep(std::time::Duration::from_secs(1)); + } + })))); + Self { bouncer_config: bouncer_config.try_into().expect("Failed to parse bouncer config."), tx_executor_config: TransactionExecutorConfig { @@ -155,6 +172,8 @@ impl PyBlockExecutor { tx_executor: None, storage: Box::new(storage), global_contract_cache: GlobalContractCache::new(global_contract_cache_size), + thread_handle, + shared_struct, } } @@ -245,6 +264,28 @@ impl PyBlockExecutor { }) .collect(); + let is_thread_alive = { + let handle = self.thread_handle.lock().unwrap(); + if let Some(handle) = handle.as_ref() { + handle.thread().unpark(); + true + } else { + false + } + }; + + if is_thread_alive { + println!("Thread is still alive"); + } else { + println!("Thread is not alive"); + } + + let shared_struct = self.shared_struct.lock().unwrap(); + if let Some(ref my_struct) = *shared_struct { + println!("MyStruct is accessible: a = {}, b = {}", my_struct.a, my_struct.b); + } else { + println!("MyStruct is not accessible"); + } // Convert to Py types and allocate it on Python's heap, to be visible for Python's // garbage collector. Python::with_gil(|py| { @@ -376,6 +417,15 @@ impl PyBlockExecutor { // contracts. let mut versioned_constants = VersionedConstants::latest_constants().clone(); versioned_constants.disable_cairo0_redeclaration = false; + let shared_struct = Arc::new(Mutex::new(None)); + let shared_struct_clone = Arc::clone(&shared_struct); + let thread_handle = Arc::new(Mutex::new(Some(thread::spawn(move || { + loop { + let mut shared_struct = shared_struct_clone.lock().unwrap(); + *shared_struct = Some(MyStruct { a: 1, b: 2 }); + thread::sleep(std::time::Duration::from_secs(1)); + } + })))); Self { bouncer_config: BouncerConfig { block_max_capacity: BouncerWeights { @@ -386,11 +436,14 @@ impl PyBlockExecutor { tx_executor_config: TransactionExecutorConfig { concurrency_config: concurrency_config.into(), }, + storage: Box::new(PapyrusStorage::new_for_testing(path, &os_config.chain_id)), chain_info: os_config.into_chain_info(), versioned_constants, tx_executor: None, global_contract_cache: GlobalContractCache::new(GLOBAL_CONTRACT_CACHE_SIZE_FOR_TEST), + thread_handle, + shared_struct, } } } @@ -413,6 +466,15 @@ impl PyBlockExecutor { #[cfg(any(feature = "testing", test))] pub fn create_for_testing_with_storage(storage: impl Storage + Send + 'static) -> Self { use blockifier::state::global_cache::GLOBAL_CONTRACT_CACHE_SIZE_FOR_TEST; + let shared_struct = Arc::new(Mutex::new(None)); + let shared_struct_clone = Arc::clone(&shared_struct); + let thread_handle = Arc::new(Mutex::new(Some(thread::spawn(move || { + loop { + let mut shared_struct = shared_struct_clone.lock().unwrap(); + *shared_struct = Some(MyStruct { a: 1, b: 2 }); + thread::sleep(std::time::Duration::from_secs(1)); + } + })))); Self { bouncer_config: BouncerConfig::max(), tx_executor_config: TransactionExecutorConfig::create_for_testing(true), @@ -421,6 +483,8 @@ impl PyBlockExecutor { versioned_constants: VersionedConstants::latest_constants().clone(), tx_executor: None, global_contract_cache: GlobalContractCache::new(GLOBAL_CONTRACT_CACHE_SIZE_FOR_TEST), + thread_handle, + shared_struct, } }