So, Object.wait() guarantees to throw InterruptedException if the interrupt status is set upon entrance, yes? Could this be added to javadoc?
On Fri, Jun 27, 2025 at 12:59 PM David Holmes <david.hol...@oracle.com> wrote: > > On 27/06/2025 5:58 pm, Pavel Rappo wrote: > > David, > > > > As you correctly identified, the edge case that I mentioned is this: > > concurrent interrupt and notify [^1]. It has nothing to do with > > spurious wake-ups or virtual threads. In fact, I've seen that with > > virtual threads Object.wait behaves exactly the same way as with > > platform threads in that regard. So I cannot report any issue here. > > > > I'm only asking about the accuracy of the javadoc contract. Say, a > > programmer uses this template from Object.wait's javadoc. > > > > synchronized (obj) { > > while ( <condition does not hold and timeout not exceeded> ) { > > long timeoutMillis = ... ; // recompute timeout values > > int nanos = ... ; > > obj.wait(timeoutMillis, nanos); > > } > > ... // Perform action appropriate to condition or timeout > > } > > > > Obviously, the programmer handles InterruptedException outside this > > template. Perhaps the programmer relies on that exception being thrown > > on an interrupt. So they think of this code as of interruptible. > > > > Now, if it is generally possible -- and not just in this edge case -- > > for Object.wait to return from an interrupt normally, the above code > > is effectively uninterruptible. And the programmer does not know about > > it. To fix that code, the programmer needs to additionally and > > explicitly check the interrupt status. > > The wait() will throw IE on the next loop if the condition is not met. > Otherwise the code proceeds with the knowledge the thread was notified, > irrespective of whether the thread was also interrupted "around the same > time". > > David > ----- > > > In contrast, j.u.c.Condition.await, makes a special provision, which > > guarantees that if the method returns normally from an interrupt, it > > will throw an exception on the next iteration of the > > j.u.c.{Lock,Condition} analogue of the above template: > > > >> If the current thread: > >> > >> has its interrupted status set on entry to this method; > >> or ... > >> then InterruptedException is thrown and the current thread's interrupted > >> status is cleared. > > > > [^1]: > > https://docs.oracle.com/javase/specs/jls/se24/html/jls-17.html#jls-17.2.4 > > > > On Fri, Jun 27, 2025 at 3:47 AM David Holmes <david.hol...@oracle.com> > > wrote: > >> > >> Hi Pavel, > >> > >> On 27/06/2025 8:23 am, Pavel Rappo wrote: > >>> Here's an interesting behaviour. A thread that has been blocked in > >>> Object.wait is interrupted. But instead of throwing an > >>> InterruptedException, Object.wait returns normally with the thread's > >>> interrupt status set. > >> > >> Do you mean it returns normally without being notified? That's allowed > >> by spec as it is just a spurious wakeup. > >> > >> That said, it shouldn't really happen in the current implementation > >> AFAIK, though with recent changes around virtual thread support it is > >> possible some new edge case has crept in. Or a bug. > >> > >> If the interrupt is racing with a notification then what you see is also > >> allowed as you can't tell which occurred first: > >> > >> "If the current thread is interrupted by any thread before or while it > >> is waiting, ... > >> > >> once notified it is no longer waiting. > >> > >>> This behaviour is not mentioned in javadoc, yet I witnessed it. > >>> Granted, I could only trigger it in an edge case described in JLS. I > >> > >> What edge case is described in current JLS? > >> > >>> wonder if the behaviour is reserved for that edge case, or it can be > >>> observed elsewhere and there is a genuine gap in javadoc. FWIW, > >>> javadoc for j.u.c.Condition documents this behaviour. > >>> > >>> Here's a practical implication of this. If some code that uses > >>> Object.wait wants to be interruptible, it must not rely on Object.wait > >>> to throw InterruptedException. It should check interrupt status or > >>> call other methods that are guaranteed to throw InterruptedException > >>> on thread interruption. > >> > >> In typical usage though if you were notified as well then responding to > >> that is generally fine and is what would happen if the notification > >> definitely occurred before the interrupt. If it was a spurious wakeup > >> then you should be re-waiting in a loop and the next wait will throw the > >> IE. So I think no real code would be adversely impacted by these edge > >> cases. > >> > >> Cheers, > >> David > >> ----- > >> > >>> -Pavel > >> >