Skip to content

Commit

Permalink
Fix main stack top detection on musl-libc
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil committed Sep 27, 2024
1 parent d58ede5 commit dc7320d
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 3 deletions.
29 changes: 26 additions & 3 deletions src/crystal/system/unix/pthread.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
11 changes: 11 additions & 0 deletions src/lib_c/aarch64-linux-musl/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -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
Expand Down
11 changes: 11 additions & 0 deletions src/lib_c/i386-linux-musl/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -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
Expand Down
11 changes: 11 additions & 0 deletions src/lib_c/x86_64-linux-musl/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -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
Expand Down

0 comments on commit dc7320d

Please sign in to comment.