From 67c208b6849627b79eea32923a45c24fd263de1d Mon Sep 17 00:00:00 2001 From: Claudia Pellegrino Date: Mon, 6 Jan 2025 18:30:37 +0100 Subject: [PATCH] [RFZDEV-30379] Unblock main thread if init fails When the monitor thread encounters an error during initialization, the main thread hangs indefinitely because the monitor thread will bail without ever releasing the synchronization lock and without signaling the `Condition` on which the main thread is waiting. Unblock the main thread by adding the signal/unlock sequence to the failure path. Additionally, throw a Java exception so we learn more about what causes the error. Co-authored-by: Jan-Niklas Dornbach Co-authored-by: Martin Mungard Co-authored-by: Richard L. Jackson --- pom.xml | 2 +- src/main/c/include/SerialImp.h | 1 + .../native/linux/x86_64/libNRJavaSerial.so | Bin 75640 -> 75304 bytes src/main/c/src/SerialImp.c | 43 +++++++--- .../io/MonitorInitializationException.java | 78 ++++++++++++++++++ src/main/java/gnu/io/RXTXPort.java | 51 ++++++++++-- .../nrjavaserial/build.properties | 2 +- 7 files changed, 157 insertions(+), 20 deletions(-) create mode 100644 src/main/java/gnu/io/MonitorInitializationException.java diff --git a/pom.xml b/pom.xml index bb8b30e7..080c0895 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.bahn nrjavaserial - 5.2.1+dbsystel2 + 5.2.1+dbsystel3 NRJavaSerial A fork of the RXTX library with a focus on ease of use and embeddability in other libraries. http://neuronrobotics.com diff --git a/src/main/c/include/SerialImp.h b/src/main/c/include/SerialImp.h index 7206d361..f3be097a 100644 --- a/src/main/c/include/SerialImp.h +++ b/src/main/c/include/SerialImp.h @@ -416,6 +416,7 @@ printf("%8li sec : %8li usec\n", enow.tv_sec - snow.tv_sec, enow.tv_sec - snow.t #define OUT_OF_MEMORY "java/lang/OutOfMemoryError" #define IO_EXCEPTION "java/io/IOException" #define PORT_IN_USE_EXCEPTION "gnu/io/PortInUseException" +#define MONITOR_INITIALIZATION_EXCEPTION "gnu/io/MonitorInitializationException" /* some popular releases of Slackware do not have SSIZE_MAX */ diff --git a/src/main/c/resources/native/linux/x86_64/libNRJavaSerial.so b/src/main/c/resources/native/linux/x86_64/libNRJavaSerial.so index 36e5d5513d34bd3db8690ff1230797944b3dde1f..18cb77c2b56083a5af183fd8fa2eb70a860a8cc8 100755 GIT binary patch literal 75304 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 VpN5y9_}NReB)!k=K75zz{{T0`AL9T3 literal 75640 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­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 + jfieldID monitorThreadInitCompletedField = (*env)->GetFieldID( env, (*env)->GetObjectClass(env, jobj), - "monitorThreadReady", + "monitorThreadInitCompleted", "Ljava/util/concurrent/locks/Condition;"); if ((*env)->ExceptionCheck(env)) { return 1; } - jobject monitorThreadReady = (*env)->GetObjectField( + jobject monitorThreadInitCompleted = (*env)->GetObjectField( env, jobj, - monitorThreadReadyField); + monitorThreadInitCompletedField); if ((*env)->ExceptionCheck(env)) { return 1; } jmethodID signal = (*env)->GetMethodID( env, - (*env)->GetObjectClass(env, monitorThreadReady), + (*env)->GetObjectClass(env, monitorThreadInitCompleted), "signal", "()V"); if ((*env)->ExceptionCheck(env)) { return 1; } - (*env)->CallVoidMethod(env, monitorThreadReady, signal); + (*env)->CallVoidMethod(env, monitorThreadInitCompleted, signal); if ((*env)->ExceptionCheck(env)) { return 1; } @@ -4250,6 +4251,7 @@ int initialise_event_info_struct( struct event_info_struct *eis ) jobject jobj = *eis->jobj; JNIEnv *env = eis->env; struct event_info_struct *index = master_index; + char message[28]; if ( eis->initialised == 1 ) goto end; @@ -4293,8 +4295,11 @@ int initialise_event_info_struct( struct event_info_struct *eis ) eis->send_event = (*env)->GetMethodID( env, eis->jclazz, "sendEvent", "(IZ)Z" ); - if(eis->send_event == NULL) + if(eis->send_event == NULL) { + throw_java_exception(env, MONITOR_INITIALIZATION_EXCEPTION, + "initialise_event_info_struct", "Unable to find `sendEvent`"); goto fail; + } end: FD_ZERO( &eis->rfds ); if (eis->fd < FD_SETSIZE && eis->fd > 0) { @@ -4304,7 +4309,10 @@ int initialise_event_info_struct( struct event_info_struct *eis ) eis->initialised = 1; return( 1 ); } else { - // you can reduce this limitation only with migration to epool or something like that. + // you can reduce this limitation only with migration to poll or something like that. + snprintf(message, sizeof(message), "fd == %i out of range", eis->fd); + throw_java_exception(env, MONITOR_INITIALIZATION_EXCEPTION, + "initialise_event_info_struct", message); } fail: report_error("initialise_event_info_struct: initialise failed!\n"); @@ -4365,10 +4373,23 @@ JNIEXPORT void JNICALL RXTXPort(eventLoop)( JNIEnv *env, jobject jobj ) eis.initialised = 0; ENTER( "eventLoop\n" ); + + /* If initialisation fails, we throw a Java exception, so the + * Java main thread has a chance to learn what went wrong. + * In that case, the monitor thread must notify the main thread + * and release the lock to avoid blocking the main thread + * indefinitely. + * We must also defer the notify/unlock sequence at least until + * the info that something went wrong has been made available + * to the main thread (via the `pendingException` field), so that + * when the main thread returns from `await`, it gets a chance + * to know that it has to bail and not enter its main loop. + * Due to that constraint, let the Java catch block be responsible + * for the notify/unlock dance if initialisation fails. */ if ( !initialise_event_info_struct( &eis ) ) goto end; if ( !init_threads( &eis ) ) goto end; - if (signal_monitor_thread_ready(env, jobj)) goto end; + if (signal_monitor_thread_init_completed(env, jobj)) goto end; if (unlock_monitor_thread(env, jobj)) goto end; do{ diff --git a/src/main/java/gnu/io/MonitorInitializationException.java b/src/main/java/gnu/io/MonitorInitializationException.java new file mode 100644 index 00000000..57c5e6e1 --- /dev/null +++ b/src/main/java/gnu/io/MonitorInitializationException.java @@ -0,0 +1,78 @@ +/*------------------------------------------------------------------------- +| RXTX License v 2.1 - LGPL v 2.1 + Linking Over Controlled Interface. +| RXTX is a native interface to serial ports in java. +| Copyright 1997-2025 by Trent Jarvi tjarvi@qbang.org and others who +| actually wrote it. See individual source files for more information. +| +| A copy of the LGPL v 2.1 may be found at +| http://www.gnu.org/licenses/lgpl.txt on March 4th 2007. A copy is +| here for your convenience. +| +| This library is free software; you can redistribute it and/or +| modify it under the terms of the GNU Lesser General Public +| License as published by the Free Software Foundation; either +| version 2.1 of the License, or (at your option) any later version. +| +| This library is distributed in the hope that it will be useful, +| but WITHOUT ANY WARRANTY; without even the implied warranty of +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +| Lesser General Public License for more details. +| +| An executable that contains no derivative of any portion of RXTX, but +| is designed to work with RXTX by being dynamically linked with it, +| is considered a "work that uses the Library" subject to the terms and +| conditions of the GNU Lesser General Public License. +| +| The following has been added to the RXTX License to remove +| any confusion about linking to RXTX. We want to allow in part what +| section 5, paragraph 2 of the LGPL does not permit in the special +| case of linking over a controlled interface. The intent is to add a +| Java Specification Request or standards body defined interface in the +| future as another exception but one is not currently available. +| +| http://www.fsf.org/licenses/gpl-faq.html#LinkingOverControlledInterface +| +| As a special exception, the copyright holders of RXTX give you +| permission to link RXTX with independent modules that communicate with +| RXTX solely through the Sun Microsytems CommAPI interface version 2, +| regardless of the license terms of these independent modules, and to copy +| and distribute the resulting combined work under terms of your choice, +| provided that every copy of the combined work is accompanied by a complete +| copy of the source code of RXTX (the version of RXTX used to produce the +| combined work), being distributed under the terms of the GNU Lesser General +| Public License plus this exception. An independent module is a +| module which is not derived from or based on RXTX. +| +| Note that people who make modified versions of RXTX are not obligated +| to grant this special exception for their modified versions; it is +| their choice whether to do so. The GNU Lesser General Public License +| gives permission to release a modified version without this exception; this +| exception also makes it possible to release a modified version which +| carries forward this exception. +| +| You should have received a copy of the GNU Lesser General Public +| License along with this library; if not, write to the Free +| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +| All trademarks belong to their respective owners. +--------------------------------------------------------------------------*/ +package gnu.io; + +/** +* The monitor thread encountered an error while initializing the +* event loop. +*/ +@SuppressWarnings("serial") +public class MonitorInitializationException extends RuntimeException +{ + public MonitorInitializationException(String str) + { + super(str); + } + public MonitorInitializationException() + { + super(); + } + public MonitorInitializationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/gnu/io/RXTXPort.java b/src/main/java/gnu/io/RXTXPort.java index f0559661..4e5bf2f6 100644 --- a/src/main/java/gnu/io/RXTXPort.java +++ b/src/main/java/gnu/io/RXTXPort.java @@ -62,6 +62,7 @@ import java.util.TooManyListenersException; import java.lang.Math; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -94,6 +95,12 @@ class MonitorThread extends Thread private volatile boolean Data=false; private volatile boolean Output=false; + /** + * Whether an exception occurred during initialization. + * The controlling thread may read and propagate it. + */ + private final AtomicReference pendingException = new AtomicReference<>(); + MonitorThread() { if (debug) @@ -112,7 +119,16 @@ public void run() eis = 0; if (debug) z.reportln( "eventLoop() returned, this is invalid."); - }catch(Throwable ex) { + } catch (MonitorInitializationException ex) { + if (debug) { + z.reportln("Error while initializing monitor thread; propagating."); + } + this.pendingException.set(ex); + if (monitorThreadState.isWriteLockedByCurrentThread()) { + monitorThreadInitCompleted.signal(); + monitorThreadState.writeLock().unlock(); + } + } catch (Throwable ex) { HARDWARE_FAULT=true; sendEvent(SerialPortEvent.HARDWARE_ERROR, true); } @@ -122,6 +138,14 @@ protected void finalize() throws Throwable if (debug) z.reportln( "RXTXPort:MonitorThread exiting"); } + + /** + * Atomically clears and returns a pending exception if initialization has failed. + * @return an exception if one is pending, null otherwise. + */ + public MonitorInitializationException popPendingException() { + return pendingException.getAndSet(null); + } } protected boolean HARDWARE_FAULT=false; protected final static boolean debug = false; @@ -180,10 +204,14 @@ public RXTXPort( String name ) throws PortInUseException monThread.setName("RXTXPortMonitor("+name+")"); monThread.start(); try { - this.monitorThreadReady.await(); + this.monitorThreadInitCompleted.await(); } catch (InterruptedException e) { z.reportln("Interrupted while waiting for the monitor thread to start!"); } + MonitorInitializationException exception = monThread.popPendingException(); + if (exception != null) { + throw exception; + } this.monitorThreadState.writeLock().unlock(); // } catch ( PortInUseException e ){} timeout = -1; /* default disabled timeout */ @@ -692,11 +720,16 @@ protected native int readTerminatedArray( byte b[], int off, int len, byte t[] ) private final Lock monitorThreadStateWriteLock = this.monitorThreadState.writeLock(); /** - * Signalled by JNI code from inside {@link #eventLoop()} when the event - * loop has finished initialization of the native data structures and is - * ready to service events. + *

Signalled by JNI code from inside {@link #eventLoop()} when the event + * loop has finished initialization of the native data structures.

+ * + *

This either means that initialization was successful (and the + * event loop is ready to service events) or an exception occurred + * during initialization. + * In the latter case, {@link MonitorThread#pendingException} contains + * a non-null value.

*/ - private final Condition monitorThreadReady = this.monitorThreadState.writeLock().newCondition(); + private final Condition monitorThreadInitCompleted = this.monitorThreadState.writeLock().newCondition(); /** Process SerialPortEvents */ native void eventLoop(); @@ -911,10 +944,14 @@ public void addEventListener( monThread.setName("RXTXPortMonitor("+name+")"); monThread.start(); try { - this.monitorThreadReady.await(); + this.monitorThreadInitCompleted.await(); } catch (InterruptedException e) { z.reportln("Interrupted while waiting for the monitor thread to start!"); } + MonitorInitializationException exception = monThread.popPendingException(); + if (exception != null) { + throw exception; + } this.monitorThreadState.writeLock().unlock(); } if (debug) diff --git a/src/main/resources/com/neuronrobotics/nrjavaserial/build.properties b/src/main/resources/com/neuronrobotics/nrjavaserial/build.properties index 819b3ec7..f016b72e 100644 --- a/src/main/resources/com/neuronrobotics/nrjavaserial/build.properties +++ b/src/main/resources/com/neuronrobotics/nrjavaserial/build.properties @@ -1,2 +1,2 @@ app.name = nrjavaserial -app.version = 5.2.1+dbsystel2 +app.version = 5.2.1+dbsystel3