Race condition prevents UART "write" call from returning
Curran D. Muhlberger
curran at muhlbergerweb.com
Tue Sep 16 05:12:10 UTC 2014
Thanks Jen,
The fix also seems to have cleared up some hangs I was seeing in I2C, so
the benefits of this extend beyond UART.
- Curran
On Mon, Sep 15, 2014 at 2:42 PM, Jen Dority <jen.dority at oracle.com> wrote:
> Hi Curran,
>
> Thanks for the bug report. I'd actually run into this issue while
> investigating your last bug report. I have a fix out for review now.
>
> Jen
>
>
>
> On 9/13/14 4:49 PM, Curran D. Muhlberger wrote:
>
>> One minor correction to my previous email: Contrary to my claim, the
>> `waitForSignal` method doesn't quite handle the case when a signal already
>> exists (though it looks like it was meant to). It neglects to assign to
>> `sig` the result of its `findTarget` call (leading to a null-pointer
>> dereference if the signal does exist). Adding this assignment lets my
>> patch work as expected, at least in my limited testing.
>> - Curran
>>
>> On Sat, Sep 13, 2014 at 1:11 PM, Curran D. Muhlberger <
>> curran at muhlbergerweb.com> wrote:
>>
>> Hello again DIO developers,
>>>
>>> There appears to be a bug in how completed writes are signaled that can
>>> prevent the UART `write` method from returning if a race condition is
>>> satisfied. Worse, the race condition seems to be satisfied most of the
>>> time.
>>>
>>> The relevant function is `Java_com_oracle_dio_uart_impl_UARTImpl_write0`
>>> in "jni_uart.cpp". Basically, the code copies the data into a
>>> newly-allocated buffer, signals a separate "write thread" that the buffer
>>> is ready, then waits for a signal indicating that the write has
>>> completed.
>>> However, after waking the "write thread", it is possible for that
>>> thread
>>> to finish its work and send the "write complete" signal before the JNI
>>> thread has had a chance to start listening. The JNI thread will the wait
>>> forever for a signal that has already been sent, causing the program to
>>> hang.
>>>
>>> To reproduce this problem reliably, simply add a `sleep` call at line 242
>>> of "jni_uart.cpp" (just before it calls `waitForSignal`), then try to
>>> invoke the `write` method on a UART device. The method will never
>>> return.
>>>
>>> I'm not sure how the DIO signaling infrastructure is designed to work, so
>>> I defer to the core developers on how best to fix this problem.
>>> However, I
>>> did find a patch that seems to do the job. In the `generateSignal`
>>> function in "dio_common.cpp", if `findTarget` returns NULL, then
>>> `generateSignal` can create a new signal and add it to the list, so that
>>> a
>>> call to `javacall_os_cond_signal` is made regardless of whether a signal
>>> already existed or not. It turns out that the `waitForSignal` method
>>> already handles this case - if a signal for the target already exists, it
>>> simply waits on it instead of creating a new one. With this small
>>> patch, I
>>> can make multiple `write` calls to a UART device without problems.
>>>
>>> Thank you for taking a look at this issue.
>>>
>>> - Curran
>>>
>>>
>
More information about the dio-dev
mailing list