Skip to content

Conversation

@george-bit
Copy link

Summary

Fixes segmentation fault when running tests with code coverage enabled (e.g., SimpleCov) on Rails 8.1+ with Ruby 3.4+.

Problem

v4.2.0 introduced negative lineno values (-1) in class_eval to fix incorrect line numbers in stack traces for Rails 8.1 ERB templates. However, this causes a segmentation fault when Ruby's Coverage module is enabled.

Root Cause

Rails 8.1 change: Rails added annotation comments to compiled ERB output (rails/rails#53731), which added an extra line and caused stack trace line numbers to be off by 1.

v4.2.0 fix: Used lineno = -1 in class_eval to compensate for the extra line.

Ruby bug: Negative line numbers in eval/class_eval cause segmentation faults when Ruby's Coverage module is running (bugs.ruby-lang.org/issues/19363). This bug exists in Ruby 3.4 and has been known since 2022.

Result: Rails 8.1 + Ruby 3.4 + view_component 4.2.0 + SimpleCov = crash.

Solution

Detect whether coverage is running via Coverage.running? and adapt:

Coverage Status lineno Stack Traces Crash?
OFF (normal use) -1 ✅ Correct No
ON (CI/SimpleCov) 1 ~2 lines off No

Why not 0? Testing showed lineno=0 also causes the segfault. 1 is the minimum safe value.

Trade-off

This is the best possible fix given the Ruby bug. Most users (development, production) get correct line numbers. Only CI/coverage users see slightly off line numbers—but their tests actually run instead of crashing.

Fixes #2540

v4.2.0 introduced a fix for incorrect line numbers in stack traces on
Rails 8.1 by using negative lineno values (-1) in class_eval. However,
negative line numbers cause segmentation faults when Ruby's Coverage
module is enabled (e.g., when using SimpleCov in CI).

This is a known Ruby bug: https://bugs.ruby-lang.org/issues/19363

The fix detects whether coverage is running via Coverage.running? and
adapts the lineno value accordingly:

- Coverage OFF: Use -1 (correct line numbers in stack traces)
- Coverage ON: Use 1 (avoids segfault, line numbers off by ~2)

Note: lineno=0 was also tested but causes the same segfault, so 1 is
the minimum safe value when coverage is enabled.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@george-bit
Copy link
Author

Question: Is there a cleaner solution?

While this fix works, I wanted to raise a question about the underlying approach.

The -1 lineno fix in v4.2.0 appears to compensate for extra lines added by Rails' annotate_rendered_view_with_filenames feature (the <!-- BEGIN ... --> / <!-- END ... --> comments). This creates a chain of workarounds:

  1. Rails 8.1 adds annotations → line numbers off by 1
  2. v4.2.0 uses lineno = -1 → line numbers correct, but segfaults with coverage
  3. This PR detects coverage → avoids segfault, but line numbers off when coverage is on

Alternative approaches worth considering:

  1. Could users just disable annotations? Setting config.action_view.annotate_rendered_view_with_filenames = false might avoid the issue entirely.

  2. Could view_component handle annotations differently? Perhaps strip them from compiled source, or account for them in a way that doesn't require negative line numbers.

  3. Is there something in the Rails 8.1 ERB compilation (beyond annotations) that requires the -1 offset?

I'm not deeply familiar with the history here, so I wanted to ask: is the current approach (adjusting lineno) the right long-term solution, or is there a cleaner way to handle Rails 8.1 compatibility that doesn't require these workarounds?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant