I have a process that makes lots of requests to a fairly slow http
server. After processing about 30k requests, a timeout exception often
kills the process. But the exception isn’t Timeout::Error, and it
doesn’t get propagated to net/http’s caller. Instead,
Timeout::AnonymousException appears to get raised AFTER Timeout.timeout
returns:
#<#Class:01x48dfad76: execution expired>
I modified jruby to log all callers to Timeout.timeout so I know the
timeout is coming from net/http. I wrapped all net/http calls to rescue
Exception, but the above exception didn’t get caught. I only managed to
rescue the above exception in the Rakefile that launches my process. The
exception is accompanied by a completely bogus stack trace that
references random code that doesn’t use timeouts.
I think raiseInThread sets RubyThread.mail to
Timeout::AnonymousException AFTER killTimeoutThread checks mail. At a
later, random point in time (after Timeout.timeout returns),
RubyThread.checkMail discovers the AnonymousException and raises it,
resulting in the exception printed above, and a bogus stack trace.
I think this happens because killTimeoutThread’s call to
timeoutFuture.get() throws an exception (and thus returns before the
Runnable that calls raiseInThread completes execution), so
RubyThread.mail gets set to Timeout::AnonymousException AFTER
context.pollThreadEvents() checks RubyThread.mail. I’m testing this
theory now. I have this problem with jruby 1.4.0. I’m also testing jruby
1.5.1 to see if I can reproduce the problem. I’m not sure it makes a
difference, but I configured net/http to timeout after 10 seconds.
Is this problem familiar to anyone? Thanks.