Catching thread exceptions (Net::IMAP timeout)

A

anselm

Hello :)

I have a question : is it possible to catch exceptions that are raised
on a thread by another thread ? Say if you have two threads, A and B
and thread A does

B.raise "bug"

Is there a way for thread B to catch and process that exception, and
resume it's execution where it was at ?

Specifcally, I am asking this because of the Net::IMAP library.
Because responses are asynchronous, the Net::IMAP library runs on two
threads. The main thread, and another thread which is there to recieve
data from the IMAP server. In most cases this works fine, because
exceptions only get raised when you are calling the Net::IMAP library
(so you can have your begin...rescue block and deal with it
appropriately).

However, as specified in the Imap4rev1 RFC, the IMAP server is allowed
to send you data without having been prompted for anything -- and one
case where it does this is when it sends a timeout message
(ByeResponseError). When the Net::IMAP library gets this message, it
raises an exception on the main thread -- and this can happen at any
time.

I can deal with the timeouts -- but I don't know how to catch that
exception in a way that allows me to resume my thread of execution !

Thanks for any help,
Anselm
 
B

Brian Candler

I have a question : is it possible to catch exceptions that are raised
on a thread by another thread ? Say if you have two threads, A and B
and thread A does

B.raise "bug"

Is there a way for thread B to catch and process that exception, and
resume it's execution where it was at ?

Well, one option is for B to start a new thread C, where it does all its
work. The original thread B hangs around in an infinite loop just catching
and processing exceptions.

require 'thread'
A = Thread.new { sleep 1; B.raise "bug" }
B = Thread.new {
C = Thread.new {
loop do
puts "Ho hum..."
sleep 3
end
}
begin
sleep 10000 while true
rescue Exception => e
puts "Hey, I got a #{e}"
retry
end
}

A.join
B.join
C.join
 
A

anselm

Well, one option is for B to start a new thread C, where it does all its
work. The original thread B hangs around in an infinite loop just catching
and processing exceptions.

Yes, this is pretty good thank you ! Maybe in my particular case I
could do it the other way round : start the imap thread from a new
thread wich will then just wait for the exception. This should then re-
raise exceptions that are not the timeout back on the main thread
(since in those cases the imap library blocks while waiting for
responses, this should not be a problem -- the exception should still
appear to come out of the imap call)

mainthread = Thread.current
imap = nil
Thread.new {
begin
limap = Net::IMAP.new('example.com')
limap.login('username', 'password')
imap = limap
sleep 10000 while true
rescue Exception => e
if e.kind_of? Net::IMAP::ByeResponseError
# deal with timeout
else
mainthread.raise e
end
end
}

# Wait for connection to be established
begin
sleep 1 while imap.nil?
rescue Exception => e
# Connection error
end

begin
imap.select('', 'INBOX')
rescue Net::IMAP::Error
# Synchronous exceptions should still be caught here
end

Thanks,
Anselm
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top