From b1b58436f2fb3aec8f54185c1437e84780f4264d Mon Sep 17 00:00:00 2001 From: Sami Salonen Date: Wed, 7 Apr 2021 21:46:36 +0300 Subject: [PATCH] [modbus] Workaround for nrjavaserial issues: do not disconnect serial (#2272) Workaround for https://github.com/openhab/openhab-core/issues/1842. Typically serial connections are disconnected and reconnected on IO errors. This has turned out to be problematic with the recent nrjavaserial updates brought by OH3 (locking behaviour of nrjavaserial seems to be prone to deadlocks). We workaround the issues by trying to keep the serial connection open as long as possible. Signed-off-by: Sami Salonen --- .../modbus/internal/ModbusManagerImpl.java | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/bundles/org.openhab.core.io.transport.modbus/src/main/java/org/openhab/core/io/transport/modbus/internal/ModbusManagerImpl.java b/bundles/org.openhab.core.io.transport.modbus/src/main/java/org/openhab/core/io/transport/modbus/internal/ModbusManagerImpl.java index 629f912b044..914579a3011 100644 --- a/bundles/org.openhab.core.io.transport.modbus/src/main/java/org/openhab/core/io/transport/modbus/internal/ModbusManagerImpl.java +++ b/bundles/org.openhab.core.io.transport.modbus/src/main/java/org/openhab/core/io/transport/modbus/internal/ModbusManagerImpl.java @@ -627,9 +627,15 @@ private , "Last try {} failed when executing request ({}). Aborting. Error was I/O error, so reseting the connection. Error details: {} {} [operation ID {}]", tryIndex, request, e.getClass().getName(), e.getMessage(), operationId); } - // Invalidate connection, and empty (so that new connection is acquired before new retry) - timer.connection.timeConsumer(c -> invalidate(endpoint, c), connection); - connection = Optional.empty(); + if (endpoint instanceof ModbusSerialSlaveEndpoint) { + // Workaround for https://github.com/openhab/openhab-core/issues/1842 + // Avoid disconnect/re-connect serial interfaces + logger.debug("Skipping invalidation of serial connection to workaround openhab-core#1842."); + } else { + // Invalidate connection, and empty (so that new connection is acquired before new retry) + timer.connection.timeConsumer(c -> invalidate(endpoint, c), connection); + connection = Optional.empty(); + } continue; } catch (ModbusIOException e) { lastError.set(new ModbusSlaveIOExceptionImpl(e)); @@ -644,9 +650,15 @@ private , "Last try {} failed when executing request ({}). Aborting. Error was I/O error, so reseting the connection. Error details: {} {} [operation ID {}]", tryIndex, request, e.getClass().getName(), e.getMessage(), operationId); } - // Invalidate connection, and empty (so that new connection is acquired before new retry) - timer.connection.timeConsumer(c -> invalidate(endpoint, c), connection); - connection = Optional.empty(); + if (endpoint instanceof ModbusSerialSlaveEndpoint) { + // Workaround for https://github.com/openhab/openhab-core/issues/1842 + // Avoid disconnect/re-connect serial interfaces + logger.debug("Skipping invalidation of serial connection to workaround openhab-core#1842."); + } else { + // Invalidate connection, and empty (so that new connection is acquired before new retry) + timer.connection.timeConsumer(c -> invalidate(endpoint, c), connection); + connection = Optional.empty(); + } continue; } catch (ModbusSlaveException e) { lastError.set(new ModbusSlaveErrorResponseExceptionImpl(e)); @@ -674,9 +686,15 @@ private , "Last try {} failed when executing request ({}). Aborting. The response did not match the request. Reseting the connection. Error details: {} {} [operation ID {}]", tryIndex, request, e.getClass().getName(), e.getMessage(), operationId); } - // Invalidate connection, and empty (so that new connection is acquired before new retry) - timer.connection.timeConsumer(c -> invalidate(endpoint, c), connection); - connection = Optional.empty(); + if (endpoint instanceof ModbusSerialSlaveEndpoint) { + // Workaround for https://github.com/openhab/openhab-core/issues/1842 + // Avoid disconnect/re-connect serial interfaces + logger.debug("Skipping invalidation of serial connection to workaround openhab-core#1842."); + } else { + // Invalidate connection, and empty (so that new connection is acquired before new retry) + timer.connection.timeConsumer(c -> invalidate(endpoint, c), connection); + connection = Optional.empty(); + } continue; } catch (ModbusException e) { lastError.set(e); @@ -717,9 +735,15 @@ private , } catch (InterruptedException e) { logger.warn("Poll task was canceled -- not executing/proceeding with the poll: {} [operation ID {}]", e.getMessage(), operationId); - // Invalidate connection, and empty (so that new connection is acquired before new retry) - timer.connection.timeConsumer(c -> invalidate(endpoint, c), connection); - connection = Optional.empty(); + if (endpoint instanceof ModbusSerialSlaveEndpoint) { + // Workaround for https://github.com/openhab/openhab-core/issues/1842 + // Avoid disconnect/re-connect serial interfaces + logger.debug("Skipping invalidation of serial connection to workaround openhab-core#1842."); + } else { + // Invalidate connection, and empty (so that new connection is acquired before new retry) + timer.connection.timeConsumer(c -> invalidate(endpoint, c), connection); + connection = Optional.empty(); + } } finally { timer.connection.timeConsumer(c -> returnConnection(endpoint, c), connection); logger.trace("Connection was returned to the pool, ending operation [operation ID {}]", operationId);