Skip to content

Commit b622606

Browse files
committed
fix: attempt to fix segfault on gha
1 parent 9bebfcd commit b622606

File tree

1 file changed

+44
-3
lines changed

1 file changed

+44
-3
lines changed

lib/hrma/build/tools.rb

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,19 @@ def execute_command(cmd:, error_message:, logger:)
246246
begin
247247
if logger
248248
logger.info("Running: #{cmd}")
249-
stdout_and_stderr_str, status = Open3.capture2e(cmd)
250-
logger.info(stdout_and_stderr_str)
249+
250+
# Use the safer non-blocking approach instead of capture2e
251+
stdout_str, stderr_str, status = safe_capture2e(cmd)
252+
253+
# Log both stdout and stderr
254+
logger.info(stdout_str + stderr_str)
255+
251256
result = status.success?
252257
logger.error(error_message) unless result
253258
result
254259
else
255-
stdout_and_stderr_str, status = Open3.capture2e(cmd)
260+
# Use the safer approach without logging
261+
_, _, status = safe_capture2e(cmd)
256262
status.success?
257263
end
258264
rescue => e
@@ -263,6 +269,41 @@ def execute_command(cmd:, error_message:, logger:)
263269
false
264270
end
265271
end
272+
273+
# A safer replacement for Open3.capture2e that avoids deadlocks
274+
# when used within Ruby Ractors
275+
#
276+
# @param cmd [String] Command to execute
277+
# @return [Array<String, String, Process::Status>] stdout, stderr, and status
278+
def safe_capture2e(cmd)
279+
Open3.popen3(cmd) do |i, o, e, t|
280+
i.close
281+
readables = [o, e]
282+
stdout = []
283+
stderr = []
284+
285+
until readables.empty?
286+
readable, = IO.select(readables)
287+
288+
if readable&.include?(o)
289+
chunk = o.read_nonblock(4096, exception: false)
290+
stdout << chunk if chunk && chunk != :wait_readable
291+
readables.delete(o) if chunk.nil?
292+
end
293+
294+
if readable&.include?(e)
295+
chunk = e.read_nonblock(4096, exception: false)
296+
stderr << chunk if chunk && chunk != :wait_readable
297+
readables.delete(e) if chunk.nil?
298+
end
299+
300+
# Remove streams that have reached EOF
301+
readables.reject!(&:eof?) if readables.any?
302+
end
303+
304+
[stdout.join, stderr.join, t.value]
305+
end
306+
end
266307
end
267308
end
268309
end

0 commit comments

Comments
 (0)