While working on AIOJ, I came across an issue with java.lang.Object.wait() and and calling java.lang.Object.notify() from a signal handler.
With POSIX AIO, there are two ways to receive notification that an I/O operation has completed. One is through a signal and the other is by calling a specified method in a temporary thread. When using signal notification, the signal is received by the thread that initiated the AIO operation.
Consider the following code snippet:
AioFuturefuture = aioChannel.read(buffer, 0L); future.get();
If aioChannel is an instance of PosixAsynchronousFileChannel, calling read invokes a native method that calls aio_read and return an AioFuture object that represents the asynchronous operation. Calling AioFuture.get() tells the current thread to block until the asynchronous operation has completed and return the number of bytes that were read.
The problem comes when we’ve configured the instance of aioChannel to use signal notifications. It seams straight forward to call java.lang.Object.wait() in the implementation of AioFuture.get(). When the signal notifies us that the asynchronous I/O operation has completed, calling java.lang.Object.notifyAll() should notify any waiting threads that they can continue. What happens in this case is that java.lang.Object.wait() gets called and while it blocks, the I/O completion gets sent to the thread. The signal handler gets called by the waiting thread. java.lang.Object.notifyAll() is called by the signal handler. When the signal handler returns, the thread is still waiting. I’m not 100% certain why this is happening but I assume it something to do with the thread not expecting to receive a notify from itself.
I have only found one workaround for this problem and that is to use a spin-lock. Unfortunately, this is less desirable because a spin-lock consumes so much CPU time. I tried calling java.lang.Object.notifyAll() from a second thread without success. It appears that once the signal handler has been called, the thread can no longer be notified. I will dig deeper into this problem and post the results here.
2 Responses
Mark Lam
April 27th, 2007 at 7:39 am
1Could it be a race condition where the notifyAll() gets called before the wait() actually occurs (or is in the midst of being executed)? Normally, you don’t have the same thread notifying itself. Hence, the fact that you have to be synchronized on the object before wait() or notifyAll() can be called on it means that you won’t have a race condition. In this case, with the signal handler being in the same thread, the synchronization doesn’t help.
mheath
April 27th, 2007 at 9:20 am
2Mark,
It’s not a race condition. I can see that wait() has been called before notifyAll() gets called. Also, I didn’t try invoking notifyAll() from the signal handler. I wouldn’t think this would work since both calls would be coming from the same thread.
I recently came across some very good documentation from Sun called the Java 2 Platform, Standard Edition 5.0: Trouble-Shooting and Diagnostic Guide available at http://java.sun.com/j2se/1.5/pdf/jdk50_ts_guide.pdf. This guide has a section on signal handling. Linking the JNI code as prescribed in this documentation improves matters a great deal. I have yet to test the wait()/notifyAll() issues but once I do I’ll blog about the results.
As far as POSIX AIO and signal handling go in AIOJ, I have it working now but under heavy loads, the signal handler is sometimes unable to obtain a reference to the JNI environment. I have some ideas on how to fix this and now just need time to test those ideas.
-Mike
RSS feed for comments on this post · TrackBack URI
Leave a reply
Categories
Archives
Links
Meta
Calendar