SF Standup 3/1/2010: JRuby skips ensure blocks when killed

When you kill a JRuby process (e.g. with a SIGINT) you can’t bank on ensure blocks being executed. Of course, this is worrisome – file handles and other connections won’t be closed. The problem boils down to this example:

4 Comments

File handles and descriptors are associated with the process. The OS will clean them up when the process dies.

March 1, 2010 at 12:16 pm

Abhi Hiremagalur says:

@Mike In the specific case that led us to this issue we were trying to ensure a connection to a JMS queue is closed gracefully; unfortunately this isn’t something the OS does when the JRuby process dies.

When the process dies, the OS should close the socket and the JMS process on the other machine get notified of the socket closure. That’s the whole point of TCP (the infamous ‘remote server closed socket unexpectedly’ error). Now of course your JMS server might misbehave in this case…

@Mike Good point – things get cleaned up eventually, although not very gracefully. But there are a lot of scenarios where app code would want to tidy up after itself (delete files, etc.) that would be skipped if it were in the rescue/ensure blocks. In this case, we’re trying to be polite to the JMS server which, as you suggested, complains when we drop connections abruptly. Fortunately, there are work-arounds (register finalizers and/or write our own signal trapping).

As we’ve researched, we’ve decided that it’s an expectations problem. As a Ruby programmer, I expect signals to raise Ruby exceptions, and trigger ensure blocks. But Java programmers have different expectations. So, it depends on whether you focus on the J(VM) part or Ruby part of JRuby.