From 3dbf5f6e2788339ef7563405e818e27267f07edd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 11 May 2026 09:52:35 +0900 Subject: [PATCH] build/command.rb: route mrbc output through tempfile to avoid pipe race The previous IO.popen capture of mrbc stdout (`-o-`) is vulnerable to a Windows MinGW race: with parallel rake (-m), stdout pipe inheritance can allow unrelated `_pp` build-progress messages from sibling worker threads to leak into the captured pipe content, corrupting the generated C file (recently seen as `CC build/...` text inside gem_test.c, causing compile errors at unrelated lines). Switch to `mrbc -o ` so the output is materialised in a file before merging into the destination, fully isolating mrbc from the parent's STDOUT. Co-authored-by: Claude --- lib/mruby/build/command.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/mruby/build/command.rb b/lib/mruby/build/command.rb index 458c166b7..d9b2f3636 100644 --- a/lib/mruby/build/command.rb +++ b/lib/mruby/build/command.rb @@ -343,16 +343,21 @@ module MRuby opt = @compile_options % {funcname: funcname} opt << " -S" if cdump opt << " -s" if static + # Have mrbc write to a private tempfile (-o) instead of stdout (-o-) + # to avoid pipe-inheritance races with parallel rake on Windows MinGW, + # where unrelated _pp build-progress lines from sibling workers can + # leak into the captured stdout and corrupt the generated C file. + tmpout = "#{out.path}.#{funcname}.mrbcout" + opt = opt.sub(/\s-o-(?=\s|\z)/, %Q[ -o "#{filename tmpout}"]) cmd = %["#{filename @command}" #{opt} #{filename(infiles).map{|f| %["#{f}"]}.join(' ')}] puts cmd if Rake.verbose - IO.popen(cmd, 'r') do |io| - out.puts io.read - end - # if mrbc execution fail, drop the file - unless $?.success? + unless system(cmd) + rm_f tmpout rm_f out.path fail "Command failed with status (#{$?.exitstatus}): [#{cmd[0,42]}...]" end + out.write File.binread(tmpout) + rm_f tmpout end end