@@ -284,7 +284,7 @@ pub enum ConsoleResult {
284284
285285impl RMain {
286286 /// Starts the main R thread and initializes the `R_MAIN` singleton.
287- /// Doesn't return.
287+ /// Doesn't return. Must be called only once.
288288 pub fn start (
289289 r_args : Vec < String > ,
290290 startup_file : Option < String > ,
@@ -298,16 +298,15 @@ impl RMain {
298298 dap : Arc < Mutex < Dap > > ,
299299 session_mode : SessionMode ,
300300 ) {
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 ( ) ) } ;
304302
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 > ( ) ;
308306
309- r_task:: initialize ( tasks_interrupt_tx. clone ( ) , tasks_idle_tx. clone ( ) ) ;
307+ r_task:: initialize ( tasks_interrupt_tx. clone ( ) , tasks_idle_tx. clone ( ) ) ;
310308
309+ unsafe {
311310 R_MAIN = Some ( RMain :: new (
312311 kernel_mutex,
313312 tasks_interrupt_rx,
@@ -320,8 +319,12 @@ impl RMain {
320319 kernel_init_tx,
321320 dap,
322321 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" ) ;
325328
326329 let mut r_args = r_args. clone ( ) ;
327330
0 commit comments