44//! writing to stdio or making HTTP requests.
55
66use core:: ffi:: c_void;
7+ use roc_env:: arg:: ArgToAndFromHost ;
78use roc_io_error:: IOErr ;
8- use roc_std:: { ReadOnlyRocList , ReadOnlyRocStr , RocBox , RocList , RocResult , RocStr } ;
9- use std:: { sync :: OnceLock , time:: Duration } ;
9+ use roc_std:: { RocBox , RocList , RocResult , RocStr } ;
10+ use std:: time:: Duration ;
1011use tokio:: runtime:: Runtime ;
1112
1213thread_local ! {
@@ -17,8 +18,6 @@ thread_local! {
1718 . unwrap( ) ;
1819}
1920
20- static ARGS : OnceLock < ReadOnlyRocList < ReadOnlyRocStr > > = OnceLock :: new ( ) ;
21-
2221/// # Safety
2322///
2423/// This function is unsafe.
@@ -289,7 +288,6 @@ pub fn init() {
289288 roc_dbg as _ ,
290289 roc_memset as _ ,
291290 roc_fx_env_dict as _ ,
292- roc_fx_args as _ ,
293291 roc_fx_env_var as _ ,
294292 roc_fx_set_cwd as _ ,
295293 roc_fx_exe_path as _ ,
@@ -341,25 +339,32 @@ pub fn init() {
341339}
342340
343341#[ no_mangle]
344- pub extern "C" fn rust_main ( args : ReadOnlyRocList < ReadOnlyRocStr > ) -> i32 {
345- ARGS . set ( args)
346- . unwrap_or_else ( |_| panic ! ( "only one thread running, must be able to set args" ) ) ;
342+ pub extern "C" fn rust_main ( args : RocList < ArgToAndFromHost > ) -> i32 {
347343 init ( ) ;
348344
349345 extern "C" {
350- #[ link_name = "roc__main_for_host_1_exposed" ]
351- pub fn roc_main_for_host_caller ( not_used : i32 ) -> i32 ;
346+ #[ link_name = "roc__main_for_host_1_exposed_generic" ]
347+ pub fn roc_main_for_host_caller (
348+ exit_code : & mut i32 ,
349+ args : * const RocList < ArgToAndFromHost > ,
350+ ) ;
352351
353352 #[ link_name = "roc__main_for_host_1_exposed_size" ]
354353 pub fn roc_main__for_host_size ( ) -> usize ;
355354 }
356355
357356 let exit_code: i32 = unsafe {
358- let code = roc_main_for_host_caller ( 0 ) ;
357+ let mut exit_code: i32 = -1 ;
358+ let args = args;
359+ roc_main_for_host_caller ( & mut exit_code, & args) ;
360+
361+ debug_assert_eq ! ( std:: mem:: size_of_val( & exit_code) , roc_main__for_host_size( ) ) ;
359362
360- debug_assert_eq ! ( std:: mem:: size_of_val( & code) , roc_main__for_host_size( ) ) ;
363+ // roc now owns the args so prevent the args from being
364+ // dropped by rust and causing a double free
365+ std:: mem:: forget ( args) ;
361366
362- code
367+ exit_code
363368 } ;
364369
365370 exit_code
@@ -370,14 +375,6 @@ pub extern "C" fn roc_fx_env_dict() -> RocList<(RocStr, RocStr)> {
370375 roc_env:: env_dict ( )
371376}
372377
373- #[ no_mangle]
374- pub extern "C" fn roc_fx_args ( ) -> ReadOnlyRocList < ReadOnlyRocStr > {
375- // Note: the clone here is no-op since the refcount is readonly. Just goes from &RocList to RocList.
376- ARGS . get ( )
377- . expect ( "args was set during init and must be here" )
378- . clone ( )
379- }
380-
381378#[ no_mangle]
382379pub extern "C" fn roc_fx_env_var ( roc_str : & RocStr ) -> RocResult < RocStr , ( ) > {
383380 roc_env:: env_var ( roc_str)
0 commit comments