Introduction
Segmentation faults in Ruby native extensions are among the hardest errors to debug because they crash the entire process with minimal Ruby stack trace. The crash originates in C code compiled as part of a gem (like nokogiri, pg, mysql2, or libv8), usually due to memory corruption, ABI mismatches, or incompatible native library versions.
Symptoms
- Ruby process exits with
SIGSEGV(signal 11) - Crash report shows
[BUG] Segmentation fault at 0x00000000000000 - Backtrace contains C-level frames, not Ruby frames
- Crash happens during specific operations (e.g., parsing XML, database query)
- Works on development machine but crashes on production server
Example crash output: ``` /path/to/ruby/bin/ruby: [BUG] Segmentation fault at 0x0000000000000010 ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]
-- Control frame information ----------------------------------------------- c:0015 p:---- s:0082 e:000081 CFUNC :parse c:0014 p:0034 s:0076 e:000075 BLOCK /path/to/nokogiri/xml/document.rb:78 ```
Common Causes
- Native library version mismatch (e.g., libyaml 0.2.x vs 0.1.x)
- Compiled gem against different OpenSSL version than runtime
- Memory corruption in C extension (use after free, buffer overflow)
- Cross-platform binary gem incompatibility
- Ruby compiled with different compiler flags than the extension
Step-by-Step Fix
- 1.Identify the crashing gem and operation:
- 2.```bash
- 3.# Run with detailed backtrace
- 4.RUBY_DEBUG_EVENT=1 bundle exec ruby -r nokogiri -e "Nokogiri::XML('<root></root>')"
# Check which native libraries the gem links against ldd $(ruby -e "puts Gem.loaded_specs['nokogiri'].full_gem_path")/lib/nokogiri/nokogiri.so ```
- 1.Check native library versions:
- 2.```bash
- 3.# For nokogiri, check libxml2 version
- 4.xml2-config --version
# Compare with what nokogiri was compiled against gem pristine nokogiri -- --use-system-libraries ```
- 1.Reinstall the gem with system libraries:
- 2.```bash
- 3.gem uninstall nokogiri
- 4.bundle config build.nokogiri --use-system-libraries
- 5.bundle install
# For pg gem: gem uninstall pg bundle config build.pg --with-pg-config=$(pg_config --bindir)/pg_config bundle install ```
- 1.Use valgrind to find memory issues (Linux):
- 2.```bash
- 3.valgrind --tool=memcheck --leak-check=full bundle exec ruby script_that_crashes.rb
- 4.
` - 5.For Alpine Linux (musl libc), use specific build flags:
- 6.```bash
- 7.bundle config build.nokogiri --use-system-libraries --with-xml2-lib=/usr/lib --with-xml2-include=/usr/include/libxml2
- 8.
`
Prevention
- Use
--use-system-librariesfor native gems to avoid bundled binary issues - Pin native library versions in your Dockerfile or deployment scripts
- Test native gem upgrades on the target OS architecture before deploying
- Use pre-compiled binary gems when available (Ruby 3.0+ supports better binary gems)
- Monitor Ruby issue tracker for known segfault bugs in your gem versions