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. 1.Identify the crashing gem and operation:
  2. 2.```bash
  3. 3.# Run with detailed backtrace
  4. 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. 1.Check native library versions:
  2. 2.```bash
  3. 3.# For nokogiri, check libxml2 version
  4. 4.xml2-config --version

# Compare with what nokogiri was compiled against gem pristine nokogiri -- --use-system-libraries ```

  1. 1.Reinstall the gem with system libraries:
  2. 2.```bash
  3. 3.gem uninstall nokogiri
  4. 4.bundle config build.nokogiri --use-system-libraries
  5. 5.bundle install

# For pg gem: gem uninstall pg bundle config build.pg --with-pg-config=$(pg_config --bindir)/pg_config bundle install ```

  1. 1.Use valgrind to find memory issues (Linux):
  2. 2.```bash
  3. 3.valgrind --tool=memcheck --leak-check=full bundle exec ruby script_that_crashes.rb
  4. 4.`
  5. 5.For Alpine Linux (musl libc), use specific build flags:
  6. 6.```bash
  7. 7.bundle config build.nokogiri --use-system-libraries --with-xml2-lib=/usr/lib --with-xml2-include=/usr/include/libxml2
  8. 8.`

Prevention

  • Use --use-system-libraries for 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