lib/cmds/io_handler.rb in cmds-0.2.9 vs lib/cmds/io_handler.rb in cmds-0.2.10

- old
+ new

@@ -1,13 +1,40 @@ class Cmds + # Class for handling IO from threads and passing it back via a {Queue} to + # the main thread for processing. + # + # NOTE These are one-use only! Don't try to reuse them. + # class IOHandler attr_accessor :in, :out, :err def initialize @in = nil @out = $stdout @err = $stderr + + # Initialize a thread-safe queue for passing output from the IO threads + # back to the main thread + # + # NOTE This used to be done in {#start}, but I was seeing intermittent + # failures on Travis from what look like thread race conditions, + # guessing that it's from output arriving before {#start} is + # called, which totally looks like it could happen. + # + # See the failure in + # + # https://travis-ci.org/nrser/qb/jobs/348609316 + # + # Really, I'm surprised I haven't hit more issues with this + # half-ass threading shit. + # + # Anyways, I moved the queue creation here, see if it helps. + # + @queue = Queue.new + + # Flag that is set to `true` when {#start} is called. + @started = false end def out= value value = value.to_s if value.is_a? Pathname @out = value @@ -20,31 +47,34 @@ def on_out &block @out = block end - # called in seperate thread handling process IO + # called in separate thread handling process IO def thread_send_out line @queue << [:out, line] end def on_err &block @err = block end - # called in seperate thread handling process IO + # called in separate thread handling process IO def thread_send_err line @queue << [:err, line] end - + + # called in separate thread handling process IO def thread_send_line sym, line @queue << [sym, line] end def start - # Initialize a thread-safe queue for passing output from the IO threads - # back to the main thread - @queue = Queue.new + if @started + raise "This handler has already been started / run" + end + + @started = true # if out is a proc, it's not done out_done = ! @out.is_a?(Proc) # same for err err_done = ! @err.is_a?(Proc)