@@ -39,7 +39,7 @@ use std::path::{Path, PathBuf};
3939use std:: pin:: pin;
4040use std:: str:: FromStr ;
4141use std:: sync:: atomic:: Ordering ;
42- use std:: sync:: { mpsc , Arc } ;
42+ use std:: sync:: Arc ;
4343use std:: time:: { Duration , Instant } ;
4444use std:: { fs, thread} ;
4545use tor_config:: { BoolOrAuto , ExplicitOrAuto } ;
@@ -153,8 +153,10 @@ pub fn random_http_probe_url() -> &'static str {
153153lazy_static ! {
154154 // It is a tor server only running instance, in case of libraries can be shared by multiple nodes and wallets
155155 static ref TOR_ARTI_INSTANCE : std:: sync:: RwLock <Option <ArtiCore >> = std:: sync:: RwLock :: new( None ) ;
156- // Tor service full restart request
157- static ref TOR_RESTART_REQUEST : std:: sync:: atomic:: AtomicBool = std:: sync:: atomic:: AtomicBool :: new( false ) ;
156+ // Tor instance ID. We can't store it with ArtiCore because of the access
157+ static ref TOR_ARTI_INSTANCE_ID : std:: sync:: atomic:: AtomicU32 = std:: sync:: atomic:: AtomicU32 :: new( 0 ) ;
158+ // Tor service full restart request. Value 0 - not requsted. Otherwise next ArtiCore instance_id
159+ static ref TOR_RESTART_REQUEST : std:: sync:: atomic:: AtomicU32 = std:: sync:: atomic:: AtomicU32 :: new( 1 ) ;
158160 // Last restarting time (need to understand how long the tor was online without any issue)
159161 static ref TOR_RESTART_TIME : std:: sync:: RwLock <Option <Instant >> = std:: sync:: RwLock :: new( None ) ;
160162 // Monitoring thread. Only one instance is allowed
@@ -244,7 +246,16 @@ pub(crate) fn get_shutdown_arti_token() -> CancellationToken {
244246
245247pub fn request_arti_restart ( reason : & str ) {
246248 info ! ( "Requestion Arti restart. Reason: {}" , reason) ;
247- TOR_RESTART_REQUEST . store ( true , Ordering :: Relaxed ) ;
249+ let next_id = TOR_ARTI_INSTANCE_ID . load ( Ordering :: SeqCst ) + 1 ;
250+ TOR_RESTART_REQUEST . store ( next_id, Ordering :: SeqCst ) ;
251+ }
252+
253+ pub fn get_next_arti_instance_id ( ) -> u32 {
254+ TOR_RESTART_REQUEST . load ( Ordering :: SeqCst )
255+ }
256+
257+ pub fn get_current_arti_instance_id ( ) -> u32 {
258+ TOR_ARTI_INSTANCE_ID . load ( Ordering :: SeqCst )
248259}
249260
250261pub fn is_arti_started ( ) -> bool {
@@ -270,12 +281,15 @@ pub fn is_arti_healthy() -> bool {
270281 Ok ( guard) => guard. is_some ( ) ,
271282 Err ( _) => false ,
272283 } ;
273- let restart_requested = TOR_RESTART_REQUEST . load ( Ordering :: Relaxed ) ;
274- has_tor && !restart_requested
284+ let restart_requested = TOR_RESTART_REQUEST . load ( Ordering :: SeqCst ) ;
285+ let tor_version = TOR_ARTI_INSTANCE_ID . load ( Ordering :: SeqCst ) ;
286+ has_tor && ( restart_requested == tor_version)
275287}
276288
277289pub fn is_arti_restarting ( ) -> bool {
278- TOR_RESTART_REQUEST . load ( Ordering :: Relaxed )
290+ let restart_requested = TOR_RESTART_REQUEST . load ( Ordering :: SeqCst ) ;
291+ let tor_version = TOR_ARTI_INSTANCE_ID . load ( Ordering :: SeqCst ) ;
292+ tor_version < restart_requested
279293}
280294
281295pub fn register_arti_active_object ( obj_name : String ) {
@@ -311,12 +325,15 @@ pub fn start_arti(
311325 let expiration_time = {
312326 let mut atri_writer = TOR_ARTI_INSTANCE . write ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
313327
328+ debug_assert ! ( atri_writer. is_none( ) ) ;
329+
314330 let create_arti_res =
315331 ArtiCore :: new ( config, base_dir, print_start_message, cleanup_arti_data) ;
316332 let ( a, expiration_time) = create_arti_res?;
317- TOR_RESTART_REQUEST . store ( false , Ordering :: Relaxed ) ;
318- * TOR_RESTART_TIME . write ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) = Some ( Instant :: now ( ) ) ;
319333 * atri_writer = Some ( a) ;
334+ TOR_RESTART_REQUEST . store ( 1 , Ordering :: SeqCst ) ;
335+ TOR_ARTI_INSTANCE_ID . store ( 1 , Ordering :: SeqCst ) ;
336+ * TOR_RESTART_TIME . write ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) = Some ( Instant :: now ( ) ) ;
320337 expiration_time
321338 } ;
322339
@@ -371,6 +388,7 @@ pub fn start_arti(
371388 } ;
372389 need_arti_restart
373390 || TOR_RESTART_REQUEST . load ( Ordering :: Relaxed )
391+ > TOR_ARTI_INSTANCE_ID . load ( Ordering :: SeqCst )
374392 || Utc :: now ( ) . timestamp ( ) > expiration_time
375393 } ;
376394
@@ -440,7 +458,10 @@ pub fn stop_arti() {
440458
441459 // Stopping the arti
442460 stop_start_arti ( false ) ;
443- TOR_RESTART_REQUEST . store ( false , Ordering :: Relaxed ) ;
461+ TOR_RESTART_REQUEST . store (
462+ TOR_ARTI_INSTANCE_ID . load ( Ordering :: SeqCst ) ,
463+ Ordering :: SeqCst ,
464+ ) ;
444465 // Checking if nothing left alive
445466 debug_assert ! ( TOR_ARTI_INSTANCE
446467 . read( )
@@ -505,7 +526,7 @@ where
505526// return expiration time
506527fn restart_arti ( start_new_client : bool ) -> i64 {
507528 error ! ( "Stopping ARTI..." ) ;
508- let ( tor_runtime, config, base_dir, restart_senders ) = {
529+ let ( tor_runtime, config, base_dir) = {
509530 let context_ids = release_arti_cancelling_all ( ) ;
510531 let mut guard = TOR_ARTI_INSTANCE . write ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ; // ? converts PoisonError to E
511532 init_arti_cancelling_all ( context_ids) ;
@@ -514,12 +535,7 @@ fn restart_arti(start_new_client: bool) -> i64 {
514535 Some ( arti) => {
515536 drop ( arti. tor_client ) ;
516537 drop ( guard) ;
517- (
518- arti. tor_runtime ,
519- arti. config ,
520- arti. base_dir ,
521- arti. restart_senders ,
522- )
538+ ( arti. tor_runtime , arti. config , arti. base_dir )
523539 }
524540 None => {
525541 error ! ( "restart_arti called for empty instance. Ignoring this call" ) ;
@@ -539,43 +555,34 @@ fn restart_arti(start_new_client: bool) -> i64 {
539555 Ok ( ( arti_core, expiration_time) ) => {
540556 info ! ( "New Arti instance is successfully created." ) ;
541557 * TOR_ARTI_INSTANCE . write ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) = Some ( arti_core) ;
542- TOR_RESTART_REQUEST . store ( false , Ordering :: Relaxed ) ;
558+ let tor_id = TOR_ARTI_INSTANCE_ID . fetch_add ( 1 , Ordering :: SeqCst ) + 1 ;
559+ debug_assert ! ( TOR_RESTART_REQUEST . load( Ordering :: SeqCst ) == tor_id) ;
560+ TOR_RESTART_REQUEST . store ( tor_id, Ordering :: SeqCst ) ;
543561 * TOR_RESTART_TIME . write ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) = Some ( Instant :: now ( ) ) ;
544562 network_status:: update_network_outage_time ( Utc :: now ( ) . timestamp ( ) ) ;
545- for sender in restart_senders {
546- let _ = sender. send ( ( ) ) ;
547- }
548563 return expiration_time;
549564 }
550565 Err ( e) => {
551566 error ! ( "Unable to create Arti instance, {}" , e) ;
552567 info ! ( "Waiting for 60 seconds before retry to create Arti instance." ) ;
553- std:: thread:: sleep ( Duration :: from_secs ( 60 ) ) ;
568+ for _ in 0 ..60 {
569+ std:: thread:: sleep ( Duration :: from_secs ( 1 ) ) ;
570+ if is_shutdown_arti ( ) {
571+ return Utc :: now ( ) . timestamp ( ) + 600 ;
572+ }
573+ }
554574 }
555575 }
556576 }
557577}
558578
559- pub fn register_arti_restart_event ( ) -> Result < std:: sync:: mpsc:: Receiver < ( ) > , Error > {
560- let mut arti_core = TOR_ARTI_INSTANCE . write ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
561- match & mut * arti_core {
562- Some ( arti_core) => {
563- let ( tx, rx) = mpsc:: channel :: < ( ) > ( ) ;
564- arti_core. restart_senders . push ( tx) ;
565- Ok ( rx)
566- }
567- None => Err ( Error :: TorProcess ( "Arti is not running" . into ( ) ) ) ,
568- }
569- }
570-
571579/// Embedded tor server - Atri
572580pub struct ArtiCore {
573581 // Using special runtime because it is the only reliable way to kill the tor_client.
574582 tor_runtime : Runtime ,
575583 tor_client : TorClient < PreferredRuntime > ,
576584 config : TorConfig ,
577585 base_dir : PathBuf ,
578- restart_senders : Vec < std:: sync:: mpsc:: Sender < ( ) > > ,
579586}
580587
581588const WEB : & str = "web" ;
@@ -676,7 +683,6 @@ impl ArtiCore {
676683 tor_client,
677684 config : config. clone ( ) ,
678685 base_dir : base_dir. into ( ) ,
679- restart_senders : Vec :: new ( ) ,
680686 } ,
681687 expiration_time,
682688 ) ) ,
0 commit comments