diff --git a/src/crystal/main.cr b/src/crystal/main.cr index 625238229c58..9b4384f16a8c 100644 --- a/src/crystal/main.cr +++ b/src/crystal/main.cr @@ -132,8 +132,8 @@ end {% if flag?(:win32) %} require "./system/win32/wmain" -{% end %} - -{% if flag?(:wasi) %} +{% elsif flag?(:wasi) %} require "./system/wasi/main" +{% else %} + require "./system/unix/main" {% end %} diff --git a/src/crystal/system/unix/main.cr b/src/crystal/system/unix/main.cr new file mode 100644 index 000000000000..1592a6342002 --- /dev/null +++ b/src/crystal/system/unix/main.cr @@ -0,0 +1,11 @@ +require "c/stdlib" + +# Prefer explicit exit over returning the status, so we are free to resume the +# main thread's fiber on any thread, without occuring a weird behavior where +# another thread returns from main when the caller might expect the main thread +# to be the one returning. + +fun main(argc : Int32, argv : UInt8**) : Int32 + status = Crystal.main(argc, argv) + LibC.exit(status) +end diff --git a/src/crystal/system/wasi/main.cr b/src/crystal/system/wasi/main.cr index 57ffd5f3f43c..9a3394809271 100644 --- a/src/crystal/system/wasi/main.cr +++ b/src/crystal/system/wasi/main.cr @@ -27,7 +27,8 @@ fun _start LibWasi.proc_exit(status) if status != 0 end -# `__main_argc_argv` is called by wasi-libc's `__main_void` with the program arguments. +# `__main_argc_argv` is called by wasi-libc's `__main_void` with the program +# arguments. fun __main_argc_argv(argc : Int32, argv : UInt8**) : Int32 main(argc, argv) end diff --git a/src/crystal/system/win32/wmain.cr b/src/crystal/system/win32/wmain.cr index 2120bfc06bfc..b1726f90329b 100644 --- a/src/crystal/system/win32/wmain.cr +++ b/src/crystal/system/win32/wmain.cr @@ -12,17 +12,13 @@ require "c/stdlib" lib LibCrystalMain end -# The actual entry point for Windows executables. This is necessary because -# *argv* (and Win32's `GetCommandLineA`) mistranslate non-ASCII characters to -# Windows-1252, so `PROGRAM_NAME` and `ARGV` would be garbled; to avoid that, we -# use this Windows-exclusive entry point which contains the correctly encoded -# UTF-16 *argv*, convert it to UTF-8, and then forward it to the original -# `main`. +# The actual entry point for Windows executables. # -# The different main functions in `src/crystal/main.cr` need not be aware that -# such an alternate entry point exists, nor that the original command line was -# not UTF-8. Thus all other aspects of program initialization still occur there, -# and uses of those main functions continue to work across platforms. +# This is necessary because *argv* (and Win32's `GetCommandLineA`) mistranslate +# non-ASCII characters to Windows-1252, so `PROGRAM_NAME` and `ARGV` would be +# garbled; to avoid that, we use this Windows-exclusive entry point which +# contains the correctly encoded UTF-16 *argv*, convert it to UTF-8, and then +# forward it to the original `main`. # # NOTE: we cannot use anything from the standard library here, including the GC. fun wmain(argc : Int32, argv : UInt16**) : Int32 @@ -46,5 +42,9 @@ fun wmain(argc : Int32, argv : UInt16**) : Int32 end LibC.free(utf8_argv) - status + # prefer explicit exit over returning the status, so we are free to resume the + # main thread's fiber on any thread, without occuring a weird behavior where + # another thread returns from main when the caller might expect the main + # thread to be the one returning. + LibC.exit(status) end