Project

General

Profile

Actions

Bug #19397

closed

ruby -h fails with SIGSGV if ulimit -s is any else than unlimited

Added by john_d_s (John Damm Soerensen) about 1 year ago. Updated about 1 year ago.

Status:
Feedback
Assignee:
-
Target version:
-
ruby -v:
ruby 3.3.0dev (2023-01-30T23:43:40Z master 7439ccf0ed) [x86_64-linux]
[ruby-core:112166]

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.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0