Fazecast / jSerialComm

Platform-independent serial port access for Java
GNU Lesser General Public License v3.0
1.34k stars 287 forks source link

Random errors when opening ports #538

Closed Lyrei-cm closed 6 months ago

Lyrei-cm commented 11 months ago

Hi there!

I'd like to preface this by thanking you ever so much for your work! It really has helped me a great deal with my project!

My app communicates with three devices via Serial Port and whenever the app is restarted (be it due to an update or just a general restart), one or two ports will refuse to connect while throwing a different error.

For instance, here's a log from two different restarts: image

Sometimes, the issue resolves itself either by waiting a few minutes after closing the app or by completely rebooting the system. This, unfortunately, is not ideal as 100% uptime is very important.

As you can see, the error on the first restart was '5 (ERROR_ACCESS_DENIED)' and on the second one '2 (ERROR_FILE_NOT_FOUND)'.

These my 'open' and 'close' functions just in case they help:

public void connect() {

        try {
            _serialPort = SerialPort.getCommPort(_portName);
            _serialPort.allowElevatedPermissionsRequest();
            if (!_serialPort.openPort())
            {
                LoggerUtils.error("Error opening port: "+_portName + " | Is port busy? " + _serialPort.isOpen() + " | Last error: " + _serialPort.getLastErrorCode() + " | Last error location: " + _serialPort.getLastErrorLocation());
                return;
            }
            _serialPort.setBaudRate(DATA_RATE);
            _serialPort.setNumDataBits(8);
            _serialPort.setNumStopBits(1);
            _serialPort.setParity(SerialPort.NO_PARITY);
            _serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
            _serialPort.setDTR();
            _serialPort.setRTS();

            _serialPort.addDataListener(this);
            isConnected.set(true);
        } catch (SerialPortInvalidPortException e) {
            LoggerUtils.error("Invalid port: "+_portName);
        }
    }

private void closeResources() {
        synchronized (lock) {
            try {
                if (_serialPort != null) {
                    LoggerUtils.debug("Removing data listener");
                    _serialPort.removeDataListener();
                    LoggerUtils.debug("Attempting to close port: " + _serialPort.closePort());
                }
            } finally {
                _serialPort = null;
                isConnected.set(false);
                isConnecting.set(false);
            }
        }
        LoggerUtils.info("Resources closed for "+_portName+".");
    }

I am using Windows 10, JDK 1.8 and version 2.10.4 of the library.

Any help/insight would be much appreciated!

hedgecrw commented 7 months ago

Sorry for the very delayed response here. I think somehow when you are receiving a "disconnected" event, your application is not properly closing the active port. An error code of 2 at the location indicated in your screen dumps means that you are trying to open a port that hasn't been closed (was already opened and still is) in the OS. Also, in your output logs, I don't see any "Removing data listener" strings which should be present if your closeResources() function is getting called, so I think what's happening is that you are getting a disconnected event and then immediately trying to call your connect() function again which creates a new Java-side serial port object for your port (which reports as "not open" because that particularly instance of the object hasn't been opened), but you aren't able to actually open it because your old/existing port is still open in the OS. The solution is to ensure you call closeResources() before calling connect() (or even better, call closeResources() as the first step inside connect() to ensure that it gets invoked).

hedgecrw commented 6 months ago

Closing as "no bug". Please re-open if the solution posted does not solve your issue.