Race condition prevents UART "write" call from returning
Curran D. Muhlberger
curran at muhlbergerweb.com
Sat Sep 13 20:11:16 UTC 2014
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