Skip to content

Fix flaky specs on TruffleRuby - #605

Merged
rymai merged 3 commits into
guard:masterfrom
andrykonchin:ak/fix-flaky-specs-on-truffleruby
Oct 1, 2026
Merged

rymai merged 3 commits into
guard:masterfrom
andrykonchin:ak/fix-flaky-specs-on-truffleruby

Conversation

@andrykonchin

@andrykonchin andrykonchin commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

What/Why

CI fails sporadically on TruffleRuby because background threads are stopped asynchronously, causing different test cases to interfere with one another.

Changes:

  • wait for Ruby threads to be stopped
  • don't run background threads in the Linux adapter unit tests

The new test failure is caused by a background thread invoking un-stubbed methods on test doubles. Whether these methods get called depends on thread scheduling and how quickly the test finishes. Preventing the background thread from running resolves the issue. This is appropriate because the background thread execution is not what this test verifies (it only checks watch event setup). The alternative -stubbing every method the background thread might invoke on test doubles - would be fragile and sub-optimal.

Actually waiting for threads (the 1st commit) isn't strictly needed to stabilize the current tests on TruffleRuby (because no thread is running in the Linux adapter unit tests anymore), but keeping synchronous thread termination ensures test cases remain properly isolated if similar background thread usage is introduced in the future.

Based on PR that was merged and rolled back #597.

New failure details

CI job logs
Listen::Adapter::Linux
  instance methods
    #stop
      when configured
        stops the worker
      when not even initialized
        does not crash
    _callback
      recognizes close_write as modify
      recognizes moved_from as moved_from
      recognizes moved_to as moved_to
    inotify max watches exceeded
      raises exception
    watch events
#<Thread:0x301f8 /home/runner/work/listen/listen/lib/listen/thread.rb:17 run> terminated with exception (report_on_exception is true):
/home/runner/work/listen/listen/vendor/bundle/truffleruby/4.0.2.10/gems/rspec-support-3.13.7/lib/rspec/support.rb:110:in 'block in <module:Support>': #<InstanceDouble(Listen::Silencer) "silencer"> received unexpected message :silenced? with ("", :dir) (RSpec::Mocks::MockExpectationError)
	from /home/runner/work/listen/listen/vendor/bundle/truffleruby/4.0.2.10/gems/rspec-support-3.13.7/lib/rspec/support.rb:119:in 'RSpec::Support.notify_failure'
	from /home/runner/work/listen/listen/vendor/bundle/truffleruby/4.0.2.10/gems/rspec-mocks-3.13.8/lib/rspec/mocks/error_generator.rb:348:in 'RSpec::Mocks::ErrorGenerator#notify'
	from /home/runner/work/listen/listen/vendor/bundle/truffleruby/4.0.2.10/gems/rspec-mocks-3.13.8/lib/rspec/mocks/error_generator.rb:332:in 'RSpec::Mocks::ErrorGenerator#__raise'
	from /home/runner/work/listen/listen/vendor/bundle/truffleruby/4.0.2.10/gems/rspec-mocks-3.13.8/lib/rspec/mocks/error_generator.rb:50:in 'RSpec::Mocks::ErrorGenerator#raise_unexpected_message_error'
	from /home/runner/work/listen/listen/vendor/bundle/truffleruby/4.0.2.10/gems/rspec-mocks-3.13.8/lib/rspec/mocks/proxy.rb:229:in 'RSpec::Mocks::Proxy#raise_unexpected_message_error'
	from /home/runner/work/listen/listen/vendor/bundle/truffleruby/4.0.2.10/gems/rspec-mocks-3.13.8/lib/rspec/mocks/test_double.rb:105:in 'RSpec::Mocks::TestDouble#method_missing'
	from /home/runner/work/listen/listen/vendor/bundle/truffleruby/4.0.2.10/gems/rspec-mocks-3.13.8/lib/rspec/mocks/verifying_double.rb:34:in 'RSpec::Mocks::VerifyingDouble#method_missing'
	from /home/runner/work/listen/listen/lib/listen/record.rb:104:in 'Listen::Record#_fast_build_dir'
	from /home/runner/work/listen/listen/lib/listen/record.rb:69:in 'Listen::Record#build'
	from /home/runner/work/listen/listen/lib/listen/adapter/base.rb:77:in 'block (3 levels) in Listen::Adapter::Base#start'
	from /home/runner/work/listen/listen/lib/listen/adapter/base.rb:97:in 'Listen::Adapter::Base#_timed'
	from /home/runner/work/listen/listen/lib/listen/adapter/base.rb:77:in 'block (2 levels) in Listen::Adapter::Base#start'
	from <internal:core> core/hash.rb:424:in 'block in Hash#each_value'
	from <internal:core> core/hash.rb:424:in 'Hash#each_pair'
	from <internal:core> core/hash.rb:424:in 'Hash#each_value'
	from /home/runner/work/listen/listen/lib/listen/adapter/base.rb:76:in 'block in Listen::Adapter::Base#start'
	from /home/runner/work/listen/listen/lib/listen/thread.rb:26:in 'Listen::Thread.rescue_and_log'
	from /home/runner/work/listen/listen/lib/listen/thread.rb:18:in 'block in Listen::Thread.new'
      starts by calling watch with default events (FAILED - 1)
  class methods
    is expected to be usable

Pending: (Failures listed here are expected and do not affect your suite's status)

  1) Listen::Adapter::Config#initialize with directories as messy array implement me
     # Not yet implemented
     # ./spec/lib/listen/adapter/config_spec.rb:87

Failures:

  1) Listen::Adapter::Linux instance methods watch events starts by calling watch with default events
     Got 2 failures:

     1.1) Failure/Error: return if @silencer.silenced?(entry.record_dir_key, :dir)
            #<InstanceDouble(Listen::Silencer) "silencer"> received unexpected message :silenced? with ("", :dir)
          # ./lib/listen/record.rb:104:in 'Listen::Record#_fast_build_dir'
          # ./lib/listen/record.rb:69:in 'Listen::Record#build'
          # ./lib/listen/adapter/base.rb:77:in 'block (3 levels) in Listen::Adapter::Base#start'
          # ./lib/listen/adapter/base.rb:97:in 'Listen::Adapter::Base#_timed'
          # ./lib/listen/adapter/base.rb:77:in 'block (2 levels) in Listen::Adapter::Base#start'
          # ./lib/listen/adapter/base.rb:76:in 'block in Listen::Adapter::Base#start'
          # ./lib/listen/thread.rb:26:in 'Listen::Thread.rescue_and_log'
          # ./lib/listen/thread.rb:18:in 'block in Listen::Thread.new'

     1.2) Failure/Error: return if @silencer.silenced?(entry.record_dir_key, :dir)
            #<InstanceDouble(Listen::Silencer) "silencer"> received unexpected message :silenced? with ("", :dir)
          # ./lib/listen/record.rb:104:in 'Listen::Record#_fast_build_dir'
          # ./lib/listen/record.rb:69:in 'Listen::Record#build'
          # ./lib/listen/adapter/base.rb:77:in 'block (3 levels) in Listen::Adapter::Base#start'
          # ./lib/listen/adapter/base.rb:97:in 'Listen::Adapter::Base#_timed'
          # ./lib/listen/adapter/base.rb:77:in 'block (2 levels) in Listen::Adapter::Base#start'
          # ./lib/listen/adapter/base.rb:76:in 'block in Listen::Adapter::Base#start'
          # ./lib/listen/thread.rb:26:in 'Listen::Thread.rescue_and_log'
          # ./lib/listen/thread.rb:18:in 'block in Listen::Thread.new'

Finished in 4 minutes 9.8 seconds (files took 2 seconds to load)
401 examples, 1 failure, 1 pending

Failed examples:

rspec ./spec/lib/listen/adapter/linux_spec.rb:55 # Listen::Adapter::Linux instance methods watch events starts by calling watch with default events

Randomized with seed 12763

Comment thread spec/lib/listen/adapter/linux_spec.rb
@rymai

rymai commented Oct 1, 2026

Copy link
Copy Markdown
Member

@andrykonchin Thanks, LGTM! ❤️

@rymai
rymai merged commit fa07357 into guard:master Oct 1, 2026
26 checks passed
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.

3 participants