RFR: 6498581: ThreadInterruptTest3 produces wrong output on Windows
Daniel D. Daugherty
daniel.daugherty at oracle.com
Thu Jan 16 12:48:18 PST 2014
On 1/16/14 1:42 PM, Yumin Qi wrote:
> David,
>
> Thanks for the detail analysis so far and supply suggested fix.
>
> On 1/15/2014 10:21 PM, David Holmes wrote:
>> Hi Yumin,
>>
>> Unfortunately the complexities of this continue to expose themselves :(
>>
>> On 15/01/2014 11:00 AM, Yumin Qi wrote:
>>> Can I have your codereview of the change
>>>
>>> http://cr.openjdk.java.net/~minqi/6498581/webrev00
>>> <http://cr.openjdk.java.net/%7Eminqi/6498581/webrev00/>
>>>
>>> Summary: There is race condition between os::interrupt and
>>> os::is_interrupted on Windows. See bug comments in detail. When thread
>>> sleep check if it gets interrupted, it may see interrupted but not
>>> really interrupted so cause spurious waking up (early return from
>>> sleep). Fix by checking if a real interrupt sent to thread interrupt
>>> event can prevent such false return. On windows we can get away the
>>> interrupted field but to keep consistent with other platforms, I choose
>>> to leave it as it is.
>>>
>>> Contributed-By: David Holmes
>>
>> Not really. :) I suggested using WaitForSingleObject on the interrupt
>> event to detect if the event was signalled or not, and hence whether
>> the thread was interrupted or not. I had envisaged it replacing use
>> of the interrupted field altogether on windows - but I had overlooked
>> the fact that the _interrupted field of osThread is maintained in
>> shared code, and further that there is an intrinsic for
>> Thread.isInterrupted that uses that field!
>>
> I can add myself after you, the main contributor for this fix.
>> The fix you have provided in os::is_interrupted deals nicely with the
>> race between setting/clearing the field and setting/clearing the
>> event. Because of the strong ordering in os::interrupt:
>>
>> 1. osthread->set_interrupted(true);
>> 2. OrderAccess::release();
>> 3. SetEvent(osthread->interrupt_event());
>>
>> we can require both conditions to be met to define that the thread is
>> indeed interrupted. If we have set the field but not the event then
>> is_interrupted will return false without touching the field or the
>> event. If the thread then blocks it will either unblock immediately
>> if setEvent has now been called, or will unblock when setEvent is
>> eventually called. That all seems to work fine.
>>
>> The intrinsic is a fast-path that inlines the access to the
>> _interrupted field, but only for the current thread and only when not
>> trying to also clear the interrupted state (ie only for
>> Thread.currentThread().isInterrupted()**). That seems mostly harmless
>> even if the thread is concurrently halfway through being interrupted
>> (ie the field is set but not the event) as any interrupt responsive
>> operation will at some point call the actual os::is_interrupted()
>> runtime code.
>>
>> The only glitch I see is that it would now be possible for the
>> following code to throw the exception:
>>
>> boolean a = Thread.currentThread().isInterrupted();
>> boolean b = Thread.interrupted();
>> if (a && !b)
>> throw new Error("inconsistent Thread interrupt state observed");
>>
> Hope no one will write code like this --- but there is other
> possibility that multiple interrupting actions sent to the thread so
> such check can not guarantee it returns consistent result. I see the
> problem here but think such coding is very rare. With we return real
> status of Event, 'a' get false means the Event is not set yet ---- and
> os::is_interrupted returns false is right.
I think you may have missed David's point here. The earlier check:
boolean a = Thread.currentThread().isInterrupted();
is returning 'true' and a later check:
boolean b = Thread.interrupted();
is returning 'false'. If variable 'a' is 'true', then 'b' must
also be 'true' to be consistent.
Dan
>
>> I don't think this is a realistic situation given for the issue to
>> arise you need the interrupting thread to be effectively descheduled
>> after setting the field but before setting the event. But still it is
>> possible and could be observable. I'm inclined to accept this
>> possibility but I think Karen should make that call. I also think we
>> would need to document this possibility just in case it does arise.
>>
>> ** I've no idea why this intrinsic exists as it is a fairly uncommon
>> usage. I guess at some point it was thought that this would be
>> common, but most interrupt responsive code uses Thread.interrupted to
>> clear the interrupt state as well as query it.
>>
> agree.
>
> Thanks
> Yumin
>> Thanks,
>> David
>>
>>>
>>> Tests: vm.quick.testlist, specjbb2005, original test case, JPRT
>>>
>>> Thanks
>>> Yumin
>>>
>>>
>
More information about the hotspot-runtime-dev
mailing list