nyholku / purejavacomm

Pure Java implementation of JavaComm SerialPort
http://www.sparetimelabs.com/purejavacomm/index.html
BSD 3-Clause "New" or "Revised" License
362 stars 146 forks source link

How to catch exception when disconnecting USB-COM device #108

Open jreker opened 6 years ago

jreker commented 6 years ago

Hello,

i am curently experimenting with PJC. I want to use it in a production enviroment. My problem is, that the lib threws a exception when i disconnect my COM device ( just unplug the cable):

This is the exception i got:

jtermios.windows.JTermiosImpl$Fail at jtermios.windows.JTermiosImpl$Port.fail(JTermiosImpl.java:100) at jtermios.windows.JTermiosImpl.select(JTermiosImpl.java:924) at jtermios.JTermios.select(JTermios.java:474) at purejavacomm.PureJavaSerialPort$3.run(PureJavaSerialPort.java:1228) at java.lang.Thread.run(Thread.java:748)

That's good, but i cannot catch the exception because it appears an another thread i think. Is there already a solution for this problem?

Thanks in advance.

nyholku commented 6 years ago

ATM there is no way to catch that except by using Thread.setDefaultUncaughtExceptionHandler and of course you can modify the PJC code.

Why do you want to catch that exception?

wbr Kusti

On 6 Aug 2018, at 17:16, jreker notifications@github.com wrote:

Hello,

i am curently experimenting with PJC. I want to use it in a production enviroment. My problem is, that the lib threws a exception when i disconnect my COM device ( just unplug the cable):

This is the exception i got:

jtermios.windows.JTermiosImpl$Fail at jtermios.windows.JTermiosImpl$Port.fail(JTermiosImpl.java:100) at jtermios.windows.JTermiosImpl.select(JTermiosImpl.java:924) at jtermios.JTermios.select(JTermios.java:474) at purejavacomm.PureJavaSerialPort$3.run(PureJavaSerialPort.java:1228) at java.lang.Thread.run(Thread.java:748)

That's good, but i cannot catch the exception because it appears an another thread i think. Is there already a solution for this problem?

Thanks in advance.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

jreker commented 6 years ago

I want to catch it, because i want to react when the device is disconnected to set a error message.

nyholku commented 6 years ago

On 7 Aug 2018, at 09:18, jreker notifications@github.com wrote:

I want to catch it, because i want to react when the device is disconnected to set a error message.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

I see.

Well, that is a legitimate wish and request.

At this point in time I think you better just hack the code, add a global catcher or do not use the event model and implement your own so you can catch the exception in your code.

Adding an event for unplug would be an extension to JavaComm spec and thus would need to be carefully considered how it is best done.

wbr Kusti

jreker commented 6 years ago

I tried to change your code but without luck. It was not working. The problem is the runnable in the constructor of the class "PureJavaSerialPort". I try to change it to callable but then the code inside the callable was not working as before.

My workaround now was that i created a watchdog thread and send periodically data to my serial device so that i will get a exception when it is not possible to send data to the device.

I was great when it is possible to integrate an event for unplug or change to code that the exception was rethrown.

Thanks BR Hannes

swarwick commented 5 years ago

I also wanted some callback to know if the main thread failed. I also resorted to using an external watch dog of sorts but in my code I do a simple check of the NativeFileDescriptor

public boolean isRunning() {
return serialPort != null && ((PureJavaSerialPort) serialPort).getNativeFileDescriptor() >= 0; // check the native file descriptor is still valid
}

I used this in my manager class like this:

   checkRunningThread = new Thread(new Runnable() {

       @Override
       public void run() {                
           int sleepMSValue = 100;
           int failedCount = 0;
           int retryCount = 10;
           int delayBetweenRetries = 1;
           int delayBetweenRetriesMS = delayBetweenRetries * 1000;
           while (shouldRun.get()) {                    
                   if (serialDevice != null && !serialDevice.isRunning()) {
                      try {                           
                          failedCount++;
                          witsProcessor.closeSerialConnection();
                          sleepMSValue = delayBetweenRetriesMS;
                      } catch (StreamBaseException e) {
                      }
                   }
                   if (serialDevice != null && serialDevice.isRunning()) {
                      failedCount = 0;
                   }
                   if (failedCount > 0 && failedCount < retryCount) {
                      try {
                          createSerialConnection();
                          getLogStatusManager().sendLogAndStatusOutput(LogLevel.INFO, LogLevel.INFO, "Control", configElement, "Serial connection created");
                          failedCount = 0;
                          sleepMSValue = 100;
                      } catch (StreamBaseException e) {
                          getLogStatusManager().sendLogAndStatusOutput(LogLevel.ERROR, LogLevel.ERROR, "Control", configElement, "Error creating serial connection: " + e.getMessage(), e);                                   
                          failedCount++;
                      }
                   }

                   if (failedCount == retryCount) {
                      getLogStatusManager().sendLogAndStatusOutput(LogLevel.ERROR, "Serial", configElement, "The serial port failed for config[" + configElement + "]");
                      failedCount++;
                   }                    
               try {
                   Thread.sleep(sleepMSValue);
               } catch (InterruptedException e) {
               }
           }
       }
   });
   checkRunningThread.start();