@@ -156,7 +156,6 @@ static R_INIT: once_cell::sync::OnceCell<()> = once_cell::sync::OnceCell::new();
156
156
static mut R_MAIN : Option < RMain > = None ;
157
157
158
158
pub struct RMain {
159
- initializing : bool ,
160
159
kernel_init_tx : Bus < KernelInfo > ,
161
160
162
161
/// Whether we are running in Console, Notebook, or Background mode.
@@ -406,17 +405,15 @@ impl RMain {
406
405
407
406
// Set up the global error handler (after support function initialization)
408
407
errors:: initialize ( ) ;
409
- }
410
408
411
- // Now that R has started (emitting any startup messages), and now that we have set
412
- // up all hooks and handlers, officially finish the R initialization process to
413
- // unblock the kernel-info request and also allow the LSP to start.
414
- RMain :: with_mut ( |main| {
415
- log:: info!(
416
- "R has started and ark handlers have been registered, completing initialization."
417
- ) ;
418
- main. complete_initialization ( ) ;
419
- } ) ;
409
+ // Now that R has started (emitting any startup messages), and now that we have set
410
+ // up all hooks and handlers, officially finish the R initialization process to
411
+ // unblock the kernel-info request and also allow the LSP to start.
412
+ RMain :: with_mut ( |main| {
413
+ log:: info!( "R has started and ark handlers have been registered, completing initialization." ) ;
414
+ main. complete_initialization ( ) ;
415
+ } ) ;
416
+ }
420
417
421
418
// Now that R has started and libr and ark have fully initialized, run site and user
422
419
// level R profiles, in that order
@@ -431,6 +428,34 @@ impl RMain {
431
428
crate :: sys:: interface:: run_r ( ) ;
432
429
}
433
430
431
+ /// Completes the kernel's initialization.
432
+ /// Unlike `RMain::start()`, this has access to `R_MAIN`'s state, such as
433
+ /// the kernel-info banner.
434
+ /// SAFETY: Can only be called from the R thread, and only once.
435
+ pub unsafe fn complete_initialization ( & mut self ) {
436
+ let version = unsafe {
437
+ let version = Rf_findVarInFrame ( R_BaseNamespace , r_symbol ! ( "R.version.string" ) ) ;
438
+ RObject :: new ( version) . to :: < String > ( ) . unwrap ( )
439
+ } ;
440
+
441
+ // Initial input and continuation prompts
442
+ let input_prompt: String = harp:: get_option ( "prompt" ) . try_into ( ) . unwrap ( ) ;
443
+ let continuation_prompt: String = harp:: get_option ( "continue" ) . try_into ( ) . unwrap ( ) ;
444
+
445
+ let kernel_info = KernelInfo {
446
+ version : version. clone ( ) ,
447
+ banner : self . banner_output . clone ( ) ,
448
+ input_prompt : Some ( input_prompt) ,
449
+ continuation_prompt : Some ( continuation_prompt) ,
450
+ } ;
451
+
452
+ log:: info!( "Sending kernel info: {version}" ) ;
453
+ self . kernel_init_tx . broadcast ( kernel_info) ;
454
+
455
+ // Thread-safe initialisation flag for R
456
+ R_INIT . set ( ( ) ) . expect ( "`R_INIT` can only be set once" ) ;
457
+ }
458
+
434
459
pub fn new (
435
460
kernel : Arc < Mutex < Kernel > > ,
436
461
tasks_interrupt_rx : Receiver < RTask > ,
@@ -445,7 +470,6 @@ impl RMain {
445
470
session_mode : SessionMode ,
446
471
) -> Self {
447
472
Self {
448
- initializing : true ,
449
473
r_request_rx,
450
474
comm_manager_tx,
451
475
stdin_request_tx,
@@ -474,14 +498,23 @@ impl RMain {
474
498
475
499
/// Wait for complete R initialization
476
500
///
477
- /// Wait for R being ready to take input (i.e. `ReadConsole` was called).
478
- /// Resolves as the same time as the `Bus<KernelInfo>` init channel does.
501
+ /// Wait for R being ready to evaluate R code. Resolves as the same time as
502
+ /// the `Bus<KernelInfo>` init channel does.
479
503
///
480
504
/// Thread-safe.
481
505
pub fn wait_r_initialized ( ) {
482
506
R_INIT . wait ( ) ;
483
507
}
484
508
509
+ /// Has R completed initialization
510
+ ///
511
+ /// I.e. is it ready to evaluate R code.
512
+ ///
513
+ /// Thread-safe.
514
+ pub fn is_r_initialized ( ) -> bool {
515
+ R_INIT . get ( ) . is_some ( )
516
+ }
517
+
485
518
/// Has the `RMain` singleton completed initialization.
486
519
///
487
520
/// This can return true when R might still not have finished starting up.
@@ -545,38 +578,6 @@ impl RMain {
545
578
thread. id ( ) == unsafe { R_MAIN_THREAD_ID . unwrap ( ) }
546
579
}
547
580
548
- /// Completes the kernel's initialization
549
- pub fn complete_initialization ( & mut self ) {
550
- if self . initializing {
551
- let version = unsafe {
552
- let version = Rf_findVarInFrame ( R_BaseNamespace , r_symbol ! ( "R.version.string" ) ) ;
553
- RObject :: new ( version) . to :: < String > ( ) . unwrap ( )
554
- } ;
555
-
556
- // Initial input and continuation prompts
557
- let input_prompt: String = harp:: get_option ( "prompt" ) . try_into ( ) . unwrap ( ) ;
558
- let continuation_prompt: String = harp:: get_option ( "continue" ) . try_into ( ) . unwrap ( ) ;
559
-
560
- let kernel_info = KernelInfo {
561
- version : version. clone ( ) ,
562
- banner : self . banner_output . clone ( ) ,
563
- input_prompt : Some ( input_prompt) ,
564
- continuation_prompt : Some ( continuation_prompt) ,
565
- } ;
566
-
567
- log:: info!( "Sending kernel info: {version}" ) ;
568
- self . kernel_init_tx . broadcast ( kernel_info) ;
569
-
570
- // Internal initialisation flag, should only be used on the R thread
571
- self . initializing = false ;
572
-
573
- // Used as thread-safe initialisation flag
574
- R_INIT . set ( ( ) ) . unwrap ( ) ;
575
- } else {
576
- log:: warn!( "Initialization already complete!" ) ;
577
- }
578
- }
579
-
580
581
/// Provides read-only access to `iopub_tx`
581
582
pub fn get_iopub_tx ( & self ) -> & Sender < IOPubMessage > {
582
583
& self . iopub_tx
@@ -1323,7 +1324,7 @@ This is a Positron limitation we plan to fix. In the meantime, you can:
1323
1324
Stream :: Stderr
1324
1325
} ;
1325
1326
1326
- if self . initializing {
1327
+ if ! RMain :: is_r_initialized ( ) {
1327
1328
// During init, consider all output to be part of the startup banner
1328
1329
self . banner_output . push_str ( & content) ;
1329
1330
return ;
0 commit comments