Bug #19397
closedruby -h fails with SIGSGV if ulimit -s is any else than unlimited
Description
This applies to all versions of ruby.
I have tried these 2.6.3 2.6.6 2.7.2 3.0.0 3.2.0
To reproduce simply set ulimit -s
to anything other than unlimited.
Then run ruby -h
(or any other invocation of ruby) and ruby will generate a SIGSEGV and core dump.
The stack trace from gdb shows that ruby has failed in reserve_stack line 1022 (for the latest from github)
gdb ruby core.11885
Core was generated by `./ruby -h'.
Program terminated with signal 11, Segmentation fault.
#0 reserve_stack (limit=0x7e9a5f4400e0 <Address 0x7e9a5f4400e0 out of bounds>,
limit@entry=0x7fffffffe000 "l=38;5;13:*.xcf=38;5;13:*.xwd=38;5;13:*.yuv=38;5;13:*.cgm=38;5;13:*.emf=38;5;13:*.axv=38;5;13:*.anx=38;5;13:*.ogv=38;5;13:*.ogx=38;5;13:*.aac=38;5;45:*.au=38;5;45:*.flac=38;5;45:*.mid=38;5;45:*.midi=3"..., size=1535999991552, size@entry=1535999995904)
at thread_pthread.c:1022
1022 limit[0] = 0;
Updated by mame (Yusuke Endoh) about 1 year ago
I cannot reproduce the issue on Ubuntu 22.10 on WSL2.
$ ulimit -s 8192
$ ruby -v
ruby 3.2.0 (2022-12-25 revision a528908271) [x86_64-linux]
$ ruby -h
Usage: ruby [switches] [--] [programfile] [arguments]
...
I think it is common for environments to have ulimit -s set to finite, but we have not received any such reports. Could you describe your environment in more detail?
Updated by nobu (Nobuyoshi Nakada) about 1 year ago
- Description updated (diff)
- Status changed from Open to Feedback
This line is just to make sure if a minimal stack is available.
In other words, it is intentional the SEGV when the stack is not enough.
It is possible to guard by a signal handler but I don't think it is worth to pay that cost for usually never happening condition.
Updated by nobu (Nobuyoshi Nakada) about 1 year ago
I mean only we can is just aborting with the insufficient stack message.
And crash when insufficient stack is very usual.
$ (ulimit -s 10; exec cat)
Segmentation fault (core dumped)
Updated by john_d_s (John Damm Soerensen) about 1 year ago
I am using Centos 7.8 and further investigations shows that the problem occurs when
soft and hard limits are equal. In our case 157286400.
Lowering the softlimit will make ruby run without error.
I have made similar tes on Ffedora 36 and here the code runs without problems.
Se the following from Centos
cat /proc/self/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 157286400 157286400 bytes
Max core file size unlimited unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 688754 688754 processes
Max open files 32768 32768 files
Max locked memory unlimited unlimited bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 688754 688754 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
./ruby -h
Segmentation fault (core dumped)
ulimit -S -s 1572
./ruby -h
Usage: /home/projects/sysadmin/people/johnd/ruby/ruby [switches] [--] [programfile] [arguments]
-0[octal] specify record separator (\0, if no argument)
-a autosplit mode with -n or -p (splits $_ into $F)
-c check syntax only
-Cdirectory cd to directory before executing your script
-d set debugging flags (set $DEBUG to true)
-e 'command' one line of script. Several -e's allowed. Omit [programfile]
-Eex[:in] specify the default external and internal character encodings
-Fpattern split() pattern for autosplit (-a)
-i[extension] edit ARGV files in place (make backup if extension supplied)
-Idirectory specify $LOAD_PATH directory (may be used more than once)
-l enable line ending processing
-n assume 'while gets(); ... end' loop around your script
-p assume loop like -n but print line also like sed
-rlibrary require the library before executing your script
-s enable some switch parsing for switches after script name
-S look for the script using PATH environment variable
-v print the version number, then turn on verbose mode
-w turn warnings on for your script
-W[level=2|:category] set warning level; 0=silence, 1=medium, 2=verbose
-x[directory] strip off text before #!ruby line and perhaps cd to directory
--jit enable JIT for the platform, same as --mjit (experimental)
--mjit enable C compiler-based JIT compiler (experimental)
-h show this message, --help for more info
cat /proc/self/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 1609728 157286400 bytes
Max core file size unlimited unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 688754 688754 processes
Max open files 32768 32768 files
Max locked memory unlimited unlimited bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 688754 688754 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
Updated by mame (Yusuke Endoh) about 1 year ago
I am using Centos 7.8 and further investigations shows that the problem occurs when
soft and hard limits are equal. In our case 157286400.
Our CI list includes CentOS 7.9, where the test passes successfully. I tried ulimit -s 8192
to set equal soft and hard limits for stack, and ruby starts successfully.
$ cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
$ ulimit -s 8192
$ grep stack /proc/self/limits
Max stack size 8388608 8388608 bytes
$ ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
$ ruby -h
Usage: /home/chkbuild/.rbenv/versions/3.1.2/bin/ruby [switches] [--] [programfile] [arguments]
...
How did you build and install ruby? Is the issue reproduced only on a particular machine? If it reproduces on another machine with CentOS 7.8, you might want to contact CentOS developers.
Updated by john_d_s (John Damm Soerensen) about 1 year ago
We see it on all of our systems.
But it gets stranger as it turns out to only happen in an interactive shell and not when executed in a shell script.
Furthermore it seems to only happen with certain combinations of soft and hard limits, though I have figured out which, but 8192/8192 also works on our systems.
For reference the build was done as per instruction in the ./doc/contributing/building_ruby.md
I have looked at the offending code in thread_pthread.c and it is using alloca() which use according to the manual is highly discouraged.
Since the code is only invoked in cases where the stack limit is not unlimited/infinity it seems not to be needed. Therefor I suggest that to consider removing the code.
Anyway we have a workaround and you can close the case.