From: "Ara.T.Howard" Date: 2004-02-26T09:24:47+09:00 Subject: Re: thread gurus please help... On Wed, 25 Feb 2004, Ara.T.Howard wrote: forgot to mention that i have $VERBOSE=nil so i don't see the "...fork terminates thread..." err msg. i assume that, in this case (forking done in open3) it is OK if that thread is terminated in the child - it obviously seem to continue running in the parent... -a > > following is a _simulation_ of a rather complex gui i'm working on. the gui > run a procedure which, itself, is communication with many other processes via > Open3::popen3 (i _need_ the stderr)... anyhow, i'm having fits getting the gui > to update and do all the io (select/read, etc). this code seems to work fine > but i am very conerned that something might bite me later... if anyone would > care to comment on the interactions between the io and threads and if this is > a reccomended approach i'd love to hear it... remember this code might look a > bit funny but it demonstrative of what my code actually does. thanks in > advance for any help/advice > > ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== > require 'tk' > require 'open3' > require 'io/wait' > require 'io/nonblock' > require 'thread' > $VERBOSE=nil > STDOUT.sync = STDERR.sync = true > Thread.abort_on_exception = true > > threads = [] > > #setup gui > root = TkRoot.new > label_a=TkLabel.new root, :text=>'label_a' > label_b=TkLabel.new root, :text=>'label_b' > label_a.pack > label_b.pack > > # start the gui running > threads << > Thread.new{ Tk.mainloop } > > # simulation of my processing loop - which is communcating with another > # process and updating a widget with it's output > def update label, program > command="ruby -e '#{ program }'" > i,o,e = Open3::popen3 command > i.close > > # we run in a thread so entire process is not blocked on io > # we DO need to wait for it to complete though, because in the real code i > # depend on values which are returned... > Thread.new do > o_done = false > e_done = false > loop do > rios, = select [o, e], nil, nil > rios.map do |rio| > break if o_done and e_done > if rio.eof? > rio == o ? o_done = true : e_done = true > next > end > # i like this better, but it hangs > # putting a critical section results in deadlock > # a semaphore is too slow... > #rio.nonblock{ text = rio.read } > > # less elegant but works... > text = '' > sleep(0.42) and Thread.pass until rio.ready? > text << rio.getc while rio.ready? > label.configure :text=>text > end > end > end.join > end > > > # start background processing which will update the labels > threads << > Thread.new{ > update label_a, '4.times{p Time.now; sleep 1}' > } > threads << > Thread.new{ > update label_b, '4.times{|i| p "foobar_#{ i }"; sleep 1}' > } > > # wait for everyone to finish > #threads.map{|t| t.join} > sleep > ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== > > -a > -- =============================================================================== | EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328 | URL :: http://www.ngdc.noaa.gov/stp/ | TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done ===============================================================================