rspec-core: --bisect deadlocks when reporting results
–bisect deadlocks when reporting results
david@davids:~/git/puppet-resource_api$ bundle exec rspec --seed 40589 --bisect=verbose --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb --exclude-pattern 'spec/{fixtures/**/*.rb,fixtures/modules/*/**/*.rb}'
Bisect started using options: "--seed 40589 --pattern spec/**{,/*/**}/*_spec.rb --exclude-pattern spec/{fixtures/**/*.rb,fixtures/modules/*/**/*.rb}" and bisect runner: :fork
Running suite to find failures...^C
Bisect aborted!
The most minimal reproduction command discovered so far is:
(Not yet enough information to provide any repro command)
Bisect aborted!
The most minimal reproduction command discovered so far is:
(Not yet enough information to provide any repro command)
david@davids:~/git/puppet-resource_api$
at the point of ctrl+c, the process has been already sitting a lot longer than the test suite would run.
stracing the processes shows the following situation:
david@davids:~$ strace -s 10000 -p 6090 -p 6096
strace: Process 6090 attached
strace: Process 6096 attached
[pid 6090] wait4(6096, <unfinished ...>
[pid 6096] ppoll([{fd=10, events=POLLOUT}], 1, NULL, NULL, 8^Cstrace: Process 6090 detached
strace: Process 6096 detached
<detached ...>
david@davids:~$
where pid 6090 is the --bisect process and pid 6096 is the child rspec process. From other traces I’ve been running, I understand that the ppoll is waiting on an IO event after/while writing the results to fd 10. Meanwhile the main process is hanging in waitpid at https://github.com/rspec/rspec-core/blob/2800fe118fa2efeb87b7bdc7888476373debf6ca/lib/rspec/core/bisect/fork_runner.rb#L95
A common reason why this might not show up in testing is if the result report in the tests is smaller than the underlying OS’s buffer size. In that case the runner process exits after writing to the buffer and the parent continues happily reading from the buffer. In my case the testsuite results are ~93kB and the processes deadlock.
Your environment
- Ruby version: ruby 2.5.5p157 (2019-03-15 revision 67260) [x86_64-linux-gnu]
- rspec-core version: 3.8.0
Steps to reproduce
- checkout https://github.com/DavidS/puppet-resource_api/tree/rspec-core-repro
bundle installthe gems according to theGemfile.lock- the following command hangs:
david@davids:~/git/puppet-resource_api$ bundle exec rspec --bisect=verbose --seed 40589 --pattern 'spec/**{,/*/**}/*_spec.rb' --exclude-pattern 'spec/{fixtures/**/*.rb,fixtures/modules/*/**/*.rb}'
Bisect started using options: "--seed 40589 --pattern spec/**{,/*/**}/*_spec.rb --exclude-pattern spec/{fixtures/**/*.rb,fixtures/modules/*/**/*.rb}" and bisect runner: :fork
Running suite to find failures...
while this creates results:
david@davids:~/git/puppet-resource_api$ bundle exec rspec --bisect=verbose --require shell --seed 40589 --pattern 'spec/**{,/*/**}/*_spec.rb' --exclude-pattern 'spec/{fixtures/**/*.rb,fixtures/modules/*/**/*.rb}'
Bisect started using options: "--require shell --seed 40589 --pattern spec/**{,/*/**}/*_spec.rb --exclude-pattern spec/{fixtures/**/*.rb,fixtures/modules/*/**/*.rb}" and bisect runner: :shell
Running suite to find failures... (2 minutes 48.2 seconds)
- Failing examples (1):
- ./spec/puppet/resource_api_spec.rb[1:16:2:1]
- Non-failing examples (1398):
- ./spec/acceptance/array_spec.rb[1:1:1]
[...]
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 20 (13 by maintainers)
Commits related to this issue
- Avoid bisect command to get stuck From Palkan in https://github.com/benoittgt/rspec_repro_bisect_deadlock/issues/1 First, I've tried to play with the number of specs which led to the interesting con... — committed to rspec/rspec-core by benoittgt 5 years ago
- Avoid bisect command to get stuck From Palkan in benoittgt/rspec_repro_bisect_deadlock#1 First, I've tried to play with the number of specs which led to the interesting conclusion: **the process han... — committed to rspec/rspec-core by benoittgt 5 years ago
- Avoid bisect command to get stuck From Palkan in benoittgt/rspec_repro_bisect_deadlock#1 First, I've tried to play with the number of specs which led to the interesting conclusion: **the process han... — committed to rspec/rspec-core by benoittgt 5 years ago
- Avoid bisect command to get stuck From Palkan in benoittgt/rspec_repro_bisect_deadlock#1 First, I've tried to play with the number of specs which led to the interesting conclusion: **the process han... — committed to rspec/rspec-core by benoittgt 5 years ago
- Avoid bisect command to get stuck From Palkan in benoittgt/rspec_repro_bisect_deadlock#1 First, I've tried to play with the number of specs which led to the interesting conclusion: **the process han... — committed to rspec/rspec-core by benoittgt 5 years ago
- Avoid bisect command to get stuck From Palkan in benoittgt/rspec_repro_bisect_deadlock#1 First, I've tried to play with the number of specs which led to the interesting conclusion: **the process han... — committed to rspec/rspec-core by benoittgt 5 years ago
- Avoid bisect command to get stuck From Palkan in benoittgt/rspec_repro_bisect_deadlock#1 First, I've tried to play with the number of specs which led to the interesting conclusion: **the process han... — committed to rspec/rspec-core by benoittgt 5 years ago
- Avoid bisect command to get stuck From Palkan in benoittgt/rspec_repro_bisect_deadlock#1 First, I've tried to play with the number of specs which led to the interesting conclusion: **the process han... — committed to rspec/rspec-core by benoittgt 5 years ago
- Avoid bisect command to get stuck From Palkan in benoittgt/rspec_repro_bisect_deadlock#1 First, I've tried to play with the number of specs which led to the interesting conclusion: **the process han... — committed to MatheusRich/rspec-core by benoittgt 5 years ago
@JonRowe Not in the next couple of weeks. I can try to find another evil martian to help with this)
Exactly 😄
Thanks a lot for the time and work y’all put into rspec.
@DavidS I’d love it if you could provide us with an isolated reproduction of this, my time is quite limited at the moment and I won’t be able to get to a reproduction containing complex code like puppet, another reason for this is to exclude the possibility of puppet itself causing the deadlock.
If it is just a buffer issue as you suggest it should be possible to trigger with only “RSpec” code right?
Alternatively I’m open to suggestions for detecting deadlocks and preventing them within RSpec itself?
I’ve contributed a PR which addresses a specific situation in which
rspec --bisecthangs.Specifically when encoding is set to UTF-8 (eg. by Rails) and the forked child process tries to send back BINARY/ASCII-8BIT encoded data to the parent, but the communication channel (
Bisect::Channel) rejects it silently due to the encoding mismatch.The parent process, whose output you’re seeing, waits indefinitely for the child process which has since errored out.
@benoittgt 's
Process::WNOHANGsolution also worked for me.@palkan comes to the same conclusion that is in my original analysis.
Process.waitpiddoes some OS-level cleanup that is sometimes necessary for the overall health of the OS. In this case of a single child process, we can be lazy and not do it at all, or defer it until all output is read and processed.Thanks, yes that triggers the issue for me, as a work around the shell runner of course works, but then I guess thats why you have #2638 open 😂