Why Thread.abort_on_exception = yes doesn't show errors?

Hi, when Thread.abort_on_exception = yes I don’t see any error log in
the
screen. Note those cases:

case 1) It’s seems correct:

t = Thread.new {
sleep 1
qwe
}
t.abort_on_exception = true

puts “hello !!!”
sleep 2
puts “END”

=>
hello !!!
test.rb:3: undefined local variable or method qwe' for main:Object (NameError) from test.rb:1:ininitialize’
from test.rb:1:in `new’
from test.rb:1

case 2) Why the error is not shown???

t = Thread.new {
sleep 1
qwe
}
t.abort_on_exception = false

puts “hello !!!”
sleep 2
puts “END”

=>
hello !!!
END

case 3) But if I do a t.join then the error is shown and the program
exists !!!:

t = Thread.new {
sleep 1
qwe
}
t.abort_on_exception = false

puts “hello !!!”
t.join
puts “END”

=>
hello !!!
test.rb:3: undefined local variable or method qwe' for main:Object (NameError) from test.rb:8:injoin’
from test.rb:8

Conclusion:

  • If a thread is joined then if that threads has a non handled exception
    the
    program will exit (except if the main program handles that exception).

  • If a thread is “abort_on_exception = true” then the program will fail
    in the
    moment the thread fails (it makes sense).

  • If a thead is “abort_on_exception = false” then nothing will occur if
    the
    threads fails, and no error output will occur. WHY ???

Any comment is appreciated.

Iñaki Baz C. wrote:

  • If a thread is joined then if that threads has a non handled exception the
    program will exit (except if the main program handles that exception).

  • If a thread is “abort_on_exception = true” then the program will fail in the
    moment the thread fails (it makes sense).

  • If a thead is “abort_on_exception = false” then nothing will occur if the
    threads fails, and no error output will occur. WHY ???

That’s all intended, IIUC. Point #1 above implies point #3: suppose
threads always reported exceptions. Then if you wrote a program to
take advantage of #1 by harvesting finished threads and handling their
exceptions in the main thread (or more generally the joining thread) you
would have spurious exception dumping. You have more control this way,
but you have to remember to either set abort_on_exception or to wrap
your thread in a handler or to join the thread later. These are three
styles, each of which has its place.

El Domingo, 20 de Julio de 2008, Joel VanderWerf escribió:

You have more control this way,
but you have to remember to either set abort_on_exception or to wrap
your thread in a handler or to join the thread later. These are three
styles, each of which has its place.

Well, thanks for the explanation but I have a doubt.

I run a thread “t2” inside thread “t1” but I don’t want “t1” to wait to
“t2”
to finish, this is: I don’t need “t1” joins “t2”.

I also don’t want the main program ends because “t2” produces an
exception
that nobody handles, but I want to see the error. Is not a way to get
this
behaviour?

The only solution I see is t1 joins t2, is it?

Thanks a lot.

El Domingo, 20 de Julio de 2008, Iñaki Baz C. escribió:

Thanks a lot for any suggestion.

Opss, I think I have the solution :slight_smile:


class GServer

    # New Thread for a new IO.
    def serve(io)

            loop do

                    data = read_IO_incoming_data()
                    Thread.new {
    begin
                              Logic::process(data)
    rescue => e
      puts "#{e.class}: #{$!}"
    end
                    }

            end # loop

    end # def serve

end # class GServer

Is it OK? :slight_smile:

Iñaki Baz C. wrote:

                    Thread.new {
    begin
                              Logic::process(data)
    rescue => e
      puts "#{e.class}: #{$!}"
    end
                    }

Yes, that’s a standard practice. That’s what I meant by “wrap your
thread in a handler” (sorry that was a bit unclear).

El Lunes, 21 de Julio de 2008, Joel VanderWerf escribió:

thread in a handler" (sorry that was a bit unclear).
Yeah, now after reading again you mail I understood it better :slight_smile:

Thanks a lot for your help.

El Domingo, 20 de Julio de 2008, Iñaki Baz C. escribió:

I also don’t want the main program ends because “t2” produces an exception
that nobody handles, but I want to see the error. Is not a way to get this
behaviour?

The only solution I see is t1 joins t2, is it?

Humm, but this is not valid for me, I explain why:

I’m using GServer, so it creates a Thread for each incoming TCP
connection and
runs “serve” method for each one.

In “serve” method I parse the TCP incoming data and process it, but I
need
this connection to remain open and accepting new data even if the
received
data hasn’t be processed yet (it’s a SIP server). So, in resume I do:


class GServer

New Thread for a new IO.

def serve(io)

loop do

  data = read_IO_incoming_data()
  Thread.new {
    Logic::process(data)
  }

end # loop

end # def serve

end # class GServer

As you see, I need the TCP connection remains open and available ALL the
time,
I can wait to process the last received data, so I run a Thread and
repeat
inmediately the loop.

Also I need that if an exception occurs in Logic::process(data) it being
shown
but don’t stop the programm (abort_on_exception = false). But in this
way I
can’t see the error output if it occurs.

How could I get showing the error into the Thread without doing a
“join”? (I
can’t do a join).

Thanks a lot for any suggestion.