diff --git a/src/crystal/system/unix/pthread.cr b/src/crystal/system/unix/pthread.cr index b55839ff2784..59c13b569da4 100644 --- a/src/crystal/system/unix/pthread.cr +++ b/src/crystal/system/unix/pthread.cr @@ -116,11 +116,26 @@ module Crystal::System::Thread ret = LibC.pthread_attr_destroy(pointerof(attr)) raise RuntimeError.from_os_error("pthread_attr_destroy", Errno.new(ret)) unless ret == 0 {% elsif flag?(:linux) %} - if LibC.pthread_getattr_np(@system_handle, out attr) == 0 - LibC.pthread_attr_getstack(pointerof(attr), pointerof(address), out _) - end + ret = LibC.pthread_getattr_np(@system_handle, out attr) + raise RuntimeError.from_os_error("pthread_getattr_np", Errno.new(ret)) unless ret == 0 + + LibC.pthread_attr_getstack(pointerof(attr), pointerof(address), out stack_size) + ret = LibC.pthread_attr_destroy(pointerof(attr)) raise RuntimeError.from_os_error("pthread_attr_destroy", Errno.new(ret)) unless ret == 0 + + # with musl-libc, the main thread does not respect `rlimit -Ss` and + # instead returns the same default stack size as non-default threads, so + # we obtain the rlimit to correct the stack address manually + {% if flag?(:musl) %} + if Thread.current_is_main? + if LibC.getrlimit(LibC::RLIMIT_STACK, out rlim) == 0 + address = address + stack_size - rlim.rlim_cur + else + raise RuntimeError.from_errno("getrlimit") + end + end + {% end %} {% elsif flag?(:openbsd) %} ret = LibC.pthread_stackseg_np(@system_handle, out stack) raise RuntimeError.from_os_error("pthread_stackseg_np", Errno.new(ret)) unless ret == 0 @@ -138,6 +153,14 @@ module Crystal::System::Thread address end + {% if flag?(:musl) %} + @@main_handle : Handle = current_handle + + def self.current_is_main? + current_handle == @@main_handle + end + {% end %} + # Warning: must be called from the current thread itself, because Darwin # doesn't allow to set the name of any thread but the current one! private def system_name=(name : String) : String diff --git a/src/lib_c/aarch64-linux-musl/c/sys/resource.cr b/src/lib_c/aarch64-linux-musl/c/sys/resource.cr index 7f550c37a622..daa583ac5895 100644 --- a/src/lib_c/aarch64-linux-musl/c/sys/resource.cr +++ b/src/lib_c/aarch64-linux-musl/c/sys/resource.cr @@ -1,4 +1,15 @@ lib LibC + alias RlimT = ULongLong + + struct Rlimit + rlim_cur : RlimT + rlim_max : RlimT + end + + fun getrlimit(Int, Rlimit*) : Int + + RLIMIT_STACK = 3 + struct RUsage ru_utime : Timeval ru_stime : Timeval diff --git a/src/lib_c/i386-linux-musl/c/sys/resource.cr b/src/lib_c/i386-linux-musl/c/sys/resource.cr index 7f550c37a622..daa583ac5895 100644 --- a/src/lib_c/i386-linux-musl/c/sys/resource.cr +++ b/src/lib_c/i386-linux-musl/c/sys/resource.cr @@ -1,4 +1,15 @@ lib LibC + alias RlimT = ULongLong + + struct Rlimit + rlim_cur : RlimT + rlim_max : RlimT + end + + fun getrlimit(Int, Rlimit*) : Int + + RLIMIT_STACK = 3 + struct RUsage ru_utime : Timeval ru_stime : Timeval diff --git a/src/lib_c/x86_64-linux-musl/c/sys/resource.cr b/src/lib_c/x86_64-linux-musl/c/sys/resource.cr index 7f550c37a622..daa583ac5895 100644 --- a/src/lib_c/x86_64-linux-musl/c/sys/resource.cr +++ b/src/lib_c/x86_64-linux-musl/c/sys/resource.cr @@ -1,4 +1,15 @@ lib LibC + alias RlimT = ULongLong + + struct Rlimit + rlim_cur : RlimT + rlim_max : RlimT + end + + fun getrlimit(Int, Rlimit*) : Int + + RLIMIT_STACK = 3 + struct RUsage ru_utime : Timeval ru_stime : Timeval