From 5d9e6fea71391756871b4b0046b79f88f471eeb2 Mon Sep 17 00:00:00 2001 From: Markus Schirp Date: Fri, 24 Oct 2014 21:34:33 +0000 Subject: [PATCH] Remove parallel use for isolation * Parallel is not thread save, causing all sorts of issues when nesting. --- config/flay.yml | 2 +- lib/mutant.rb | 3 --- lib/mutant/isolation.rb | 18 ++++++++++++++++-- spec/spec_helper.rb | 1 + spec/unit/mutant/isolation_spec.rb | 20 +++++++++++++++----- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/config/flay.yml b/config/flay.yml index 12a5366d..88376657 100644 --- a/config/flay.yml +++ b/config/flay.yml @@ -1,3 +1,3 @@ --- threshold: 18 -total_score: 1118 +total_score: 1126 diff --git a/lib/mutant.rb b/lib/mutant.rb index 996cf071..6b7a3eb8 100644 --- a/lib/mutant.rb +++ b/lib/mutant.rb @@ -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 diff --git a/lib/mutant/isolation.rb b/lib/mutant/isolation.rb index 7b29eff6..33438b4b 100644 --- a/lib/mutant/isolation.rb +++ b/lib/mutant/isolation.rb @@ -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 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 302fcc02..c0202ef4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -16,6 +16,7 @@ if ENV['COVERAGE'] == 'true' end end +require 'tempfile' require 'concord' require 'adamantium' require 'devtools/spec_helper' diff --git a/spec/unit/mutant/isolation_spec.rb b/spec/unit/mutant/isolation_spec.rb index 0649b805..b7fb4f41 100644 --- a/spec/unit/mutant/isolation_spec.rb +++ b/spec/unit/mutant/isolation_spec.rb @@ -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