@@ -5,6 +5,8 @@ module Testing
5
5
module Isolation
6
6
require "thread"
7
7
8
+ SubprocessCrashed = Class . new ( StandardError )
9
+
8
10
def self . included ( klass ) # :nodoc:
9
11
klass . class_eval do
10
12
parallelize_me!
@@ -16,10 +18,17 @@ def self.forking_env?
16
18
end
17
19
18
20
def run
19
- serialized = run_in_isolation do
21
+ status , serialized = run_in_isolation do
20
22
super
21
23
end
22
24
25
+ unless status &.success?
26
+ error = SubprocessCrashed . new ( "Subprocess exited with an error: #{ status . inspect } \n output: #{ serialized . inspect } " )
27
+ error . set_backtrace ( caller )
28
+ self . failures << Minitest ::UnexpectedError . new ( error )
29
+ return defined? ( Minitest ::Result ) ? Minitest ::Result . from ( self ) : dup
30
+ end
31
+
23
32
Marshal . load ( serialized )
24
33
end
25
34
@@ -50,13 +59,13 @@ def run_in_isolation(&blk)
50
59
end
51
60
52
61
write . puts [ result ] . pack ( "m" )
53
- exit!
62
+ exit! ( 0 )
54
63
end
55
64
56
65
write . close
57
66
result = read . read
58
- Process . wait2 ( pid )
59
- result . unpack1 ( "m" )
67
+ _ , status = Process . wait2 ( pid )
68
+ return status , result . unpack1 ( "m" )
60
69
end
61
70
end
62
71
end
@@ -75,7 +84,7 @@ def run_in_isolation(&blk)
75
84
File . open ( ENV [ "ISOLATION_OUTPUT" ] , "w" ) do |file |
76
85
file . puts [ Marshal . dump ( test_result ) ] . pack ( "m" )
77
86
end
78
- exit!
87
+ exit! ( 0 )
79
88
else
80
89
Tempfile . open ( "isolation" ) do |tmpfile |
81
90
env = {
@@ -93,13 +102,14 @@ def run_in_isolation(&blk)
93
102
94
103
child = IO . popen ( [ env , Gem . ruby , *load_path_args , $0, *ORIG_ARGV , test_opts ] )
95
104
105
+ status = nil
96
106
begin
97
- Process . wait ( child . pid )
107
+ _ , status = Process . wait2 ( child . pid )
98
108
rescue Errno ::ECHILD # The child process may exit before we wait
99
109
nil
100
110
end
101
111
102
- return tmpfile . read . unpack1 ( "m" )
112
+ return status , tmpfile . read . unpack1 ( "m" )
103
113
end
104
114
end
105
115
end
0 commit comments