I think you have 3 options.
You could return the exception to the calling thread:
def receive_packet
raise "Exception in #{Thread.current}"
rescue Exception => exp
return exp
end
t1 = Thread.new do
receive_packet
end
puts "t1: #{t1.value.inspect}"
You could catch the exception on joining the thread (note you could reraise here or use an ensure block to make sure your socket is closed):
def receive_packet
raise "Exception in #{Thread.current}"
rescue Exception => exp
# reraise the exception
raise exp
end
t = Thread.new do
receive_packet
end
begin
t.join
rescue => e
puts "Exception caught from joined thread #{e.message} "
end
or you set #abort_on_exception = true so that exceptions kill all threads:
Thread.abort_on_exception = true
begin
Thread.new do
receive_packet
end
sleep 1
rescue => e
puts "Exception raised immediately to main thread: #{e.message}"
end
Update Based on what you have above and your comment I guess you need to wait for the threads calling receive_packet to finish. So you would have to join them:
class Client
def self.connect(*args, &block)
client = Client.new(*args)
client.connect(&block)
return client
end
def initialize(args)
@count = 0
end
def connect(clientid=nil)
puts "Connecting. Thread.current is #{Thread.current}"
# Start packet reading thread
@read_thread = Thread.new(Thread.current) do |parent|
Thread.current[:parent] = parent
loop { receive_packet }
end
end
def receive_packet
begin
# Poll socket - is there data waiting?
# result = IO.select([@socket], nil, nil, SELECT_TIMEOUT)
sleep 0.1
@count += 1
puts "count is now #{@count}"
if @count == 3
raise "WOOT: #{@count}"
end
# Pass exceptions up to parent thread
rescue Exception => exp
unless @socket.nil?
@socket.close
@socket = nil
end
puts "Reraising error #{exp.inspect} from #{Thread.current} to #{Thread.current[:parent]}"
Thread.current[:parent].raise(exp)
end
end
end
class MQTT
def self.connect
@client = Client.connect(options = {})
end
end
begin
MQTT.connect
Thread.list.each do |t|
# Wait for the thread to finish if it isn't this thread (i.e. the main thread).
t.join if t != Thread.current
end
rescue => e
puts "Exception from child thread: #{e.inspect}"
end