Remove parallel use for isolation

* Parallel is not thread save, causing all sorts of issues when nesting.
This commit is contained in:
Markus Schirp 2014-10-24 21:34:33 +00:00
parent cb814cd529
commit 5d9e6fea71
5 changed files with 33 additions and 11 deletions

View file

@ -1,3 +1,3 @@
---
threshold: 18
total_score: 1118
total_score: 1126

View file

@ -17,9 +17,6 @@ require 'morpher'
require 'parallel'
require 'open3'
# Mutant uses parallel with the `:in_threads` option.
# By default ruby does silently ignore errors raised in threads.
#
# This setting is done to make errors within the parallel
# reporter / execution visible in the main thread.
Thread.abort_on_exception = true

View file

@ -38,8 +38,22 @@ module Mutant
# @api private
#
def self.call(&block)
Parallel.map([block], in_processes: 1, &block.method(:call)).first
rescue Parallel::DeadWorker => exception
reader, writer = IO.pipe
pid = fork do
File.open('/dev/null', 'w') do |file|
$stderr.reopen(file)
reader.close
writer.write(Marshal.dump(block.call))
writer.close
end
end
writer.close
result = Marshal.load(reader.read)
Process.waitpid(pid)
result
rescue => exception
fail Error, exception
end

View file

@ -16,6 +16,7 @@ if ENV['COVERAGE'] == 'true'
end
end
require 'tempfile'
require 'concord'
require 'adamantium'
require 'devtools/spec_helper'

View file

@ -39,19 +39,29 @@ RSpec.describe Mutant::Isolation::Fork do
expect(object.call { :foo }).to be(:foo)
end
it 'wraps Parallel::DeadWorker exceptions' do
expect { object.call { fail Parallel::DeadWorker } }.to raise_error(Mutant::Isolation::Error)
it 'wraps exceptions' do
expect { object.call { fail } }.to raise_error(Mutant::Isolation::Error)
end
it 'wraps Parallel::DeadWorker exceptions caused by crashing ruby' do
it 'wraps exceptions caused by crashing ruby' do
expect do
object.call do
# Silence rb_bug writes
$stderr.reopen(File.open('/dev/null', 'w'))
fail RbBug.call
end
end.to raise_error(Mutant::Isolation::Error)
end
it 'redirects $stderr of children to /dev/null' do
begin
Tempfile.open('mutant-test') do |file|
$stderr = file
object.call { $stderr.puts('test') }
file.rewind
expect(file.read).to eql('')
end
ensure
$stderr = STDERR
end
end
end
end