@@ -284,7 +284,7 @@ pub enum ConsoleResult {
284
284
285
285
impl RMain {
286
286
/// Starts the main R thread and initializes the `R_MAIN` singleton.
287
- /// Doesn't return.
287
+ /// Doesn't return. Must be called only once.
288
288
pub fn start (
289
289
r_args : Vec < String > ,
290
290
startup_file : Option < String > ,
@@ -298,16 +298,15 @@ impl RMain {
298
298
dap : Arc < Mutex < Dap > > ,
299
299
session_mode : SessionMode ,
300
300
) {
301
- // Initialize global state (ensure we only do this once!)
302
- R_MAIN_INIT . get_or_init ( || unsafe {
303
- R_MAIN_THREAD_ID = Some ( std:: thread:: current ( ) . id ( ) ) ;
301
+ unsafe { R_MAIN_THREAD_ID = Some ( std:: thread:: current ( ) . id ( ) ) } ;
304
302
305
- // Channels to send/receive tasks from auxiliary threads via `RTask`s
306
- let ( tasks_interrupt_tx, tasks_interrupt_rx) = unbounded :: < RTask > ( ) ;
307
- let ( tasks_idle_tx, tasks_idle_rx) = unbounded :: < RTask > ( ) ;
303
+ // Channels to send/receive tasks from auxiliary threads via `RTask`s
304
+ let ( tasks_interrupt_tx, tasks_interrupt_rx) = unbounded :: < RTask > ( ) ;
305
+ let ( tasks_idle_tx, tasks_idle_rx) = unbounded :: < RTask > ( ) ;
308
306
309
- r_task:: initialize ( tasks_interrupt_tx. clone ( ) , tasks_idle_tx. clone ( ) ) ;
307
+ r_task:: initialize ( tasks_interrupt_tx. clone ( ) , tasks_idle_tx. clone ( ) ) ;
310
308
309
+ unsafe {
311
310
R_MAIN = Some ( RMain :: new (
312
311
kernel_mutex,
313
312
tasks_interrupt_rx,
@@ -320,8 +319,12 @@ impl RMain {
320
319
kernel_init_tx,
321
320
dap,
322
321
session_mode,
323
- ) ) ;
324
- } ) ;
322
+ ) )
323
+ } ;
324
+
325
+ // Let other threads know that `R_MAIN` is initialized. Deliberately
326
+ // panic if already set as `start()` must be called only once.
327
+ R_MAIN_INIT . set ( ( ) ) . expect ( "R can only be initialized once" ) ;
325
328
326
329
let mut r_args = r_args. clone ( ) ;
327
330
0 commit comments