@@ -162,9 +162,6 @@ thread_local! {
162162 pub static R_MAIN : RefCell <UnsafeCell <RMain >> = panic!( "Must access `R_MAIN` from the R thread" ) ;
163163}
164164
165- /// Banner output accumulated during startup
166- static mut R_BANNER : String = String :: new ( ) ;
167-
168165pub struct RMain {
169166 kernel_init_tx : Bus < KernelInfo > ,
170167
@@ -229,6 +226,13 @@ pub struct RMain {
229226 pub positron_ns : Option < RObject > ,
230227
231228 pending_lines : Vec < String > ,
229+
230+ /// Banner output accumulated during startup
231+ r_banner : String ,
232+
233+ /// Raw error buffer provided to `Rf_error()` when throwing `r_read_console()` errors.
234+ /// Stored in `RMain` to avoid memory leakage when `Rf_error()` jumps.
235+ r_error_buffer : Option < CString > ,
232236}
233237
234238/// Represents the currently active execution request from the frontend. It
@@ -513,7 +517,7 @@ impl RMain {
513517
514518 let kernel_info = KernelInfo {
515519 version : version. clone ( ) ,
516- banner : R_BANNER . clone ( ) ,
520+ banner : self . r_banner . clone ( ) ,
517521 input_prompt : Some ( input_prompt) ,
518522 continuation_prompt : Some ( continuation_prompt) ,
519523 } ;
@@ -563,6 +567,8 @@ impl RMain {
563567 session_mode,
564568 positron_ns : None ,
565569 pending_lines : Vec :: new ( ) ,
570+ r_banner : String :: new ( ) ,
571+ r_error_buffer : None ,
566572 }
567573 }
568574
@@ -1590,14 +1596,14 @@ impl RMain {
15901596 Err ( err) => panic ! ( "Failed to read from R buffer: {err:?}" ) ,
15911597 } ;
15921598
1599+ let r_main = RMain :: get_mut ( ) ;
1600+
15931601 if !RMain :: is_initialized ( ) {
15941602 // During init, consider all output to be part of the startup banner
1595- unsafe { R_BANNER . push_str ( & content) } ;
1603+ r_main . r_banner . push_str ( & content) ;
15961604 return ;
15971605 }
15981606
1599- let r_main = RMain :: get_mut ( ) ;
1600-
16011607 // To capture the current `debug: <call>` output, for use in the debugger's
16021608 // match based fallback
16031609 r_main. dap . handle_stdout ( & content) ;
@@ -1950,17 +1956,12 @@ pub extern "C" fn r_read_console(
19501956 return 0 ;
19511957 } ,
19521958 ConsoleResult :: Error ( err) => {
1953- // Save error message to a global buffer to avoid leaking memory
1959+ // Save error message to `RMain`'s buffer to avoid leaking memory
19541960 // when `Rf_error()` jumps. Some gymnastics are required to deal
19551961 // with the possibility of `CString` conversion failure since the
19561962 // error message comes from the frontend and might be corrupted.
1957- static mut ERROR_BUF : Option < CString > = None ;
1958-
1959- unsafe {
1960- ERROR_BUF = Some ( new_cstring ( format ! ( "\n {err}" ) ) ) ;
1961- }
1962-
1963- unsafe { Rf_error ( ERROR_BUF . as_ref ( ) . unwrap ( ) . as_ptr ( ) ) } ;
1963+ main. r_error_buffer = Some ( new_cstring ( format ! ( "\n {err}" ) ) ) ;
1964+ unsafe { Rf_error ( main. r_error_buffer . as_ref ( ) . unwrap ( ) . as_ptr ( ) ) } ;
19641965 } ,
19651966 } ;
19661967}
0 commit comments