google-code-export / openhab

Automatically exported from code.google.com/p/openhab
GNU General Public License v3.0
0 stars 0 forks source link

modbus serial binding crashes JVM if modbus master is disconnected #430

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?

1. Install openhab as described  here 
https://code.google.com/p/openhab/wiki/Setup

2. Copy modbus binding into addons directory

3. Configure modbus:
modbus:poll=200
modbus:serial.slave1.connection=/dev/ttyUSB0:115200
modbus:serial.slave1.id=1
modbus:serial.slave1.start=0
modbus:serial.slave1.length=9
modbus:serial.slave1.type=holding

4. Plug usb modbus master into usb port. Make sure usb master appeared in /dev/ 
directory as configured in modbus:serial.slave1.connection, othervice change 
connection string.

5. Start openhab: sudo ./start_debug.sh

6. Verify that openhab started to pull modbus slave(s)

7. Unplug modbus master from usb

What is the expected output? What do you see instead?
Expected behaviour: openhab crash should not occur.

Behaviour: openhab crash occurs
Last output:
execute try 1 error: I/O failed to write
execute try 2 error: I/O failed to write
19:51:44.528 DEBUG o.o.b.m.internal.ModbusSlave[:338] - ModbusSlave:I/O failed 
to write
19:51:44.535 INFO  o.o.b.m.internal.ModbusSlave[:306] - ModbusSlave error 
getting responce from slave
/dev/ttyUSB0: No such file or directory

What version of the product are you using? On what operating system?
Ubuntu 13.04
Openhab 1.2.0
Openhab 1.3.0. I was able to reproduce it under debugger with latest source. 
Cannot reproduce with Openhab 1.3.0 SNAPSHOT because of issue #426 
(https://code.google.com/p/openhab/issues/detail?id=426)

Please provide any additional information below.

Crash occurs in class ModbusSerialSlave here:
    public boolean connect() {
        try {

            if (connection == null) {
                SerialParameters params = new SerialParameters();
                params.setPortName(port);
                params.setBaudRate(baud);
                params.setDatabits(8);
                params.setParity("None");
                params.setStopbits(1);
                params.setEncoding(Modbus.SERIAL_ENCODING_RTU);
                params.setEcho(false);
                connection = new SerialConnection(params);
>> CRASH IS HERE >>>>>>     connection.open();

In connection.open():
                        //2. open the port, wait for given timeout
                        try {
                          m_SerialPort = (SerialPort)
>> CRASH IS HERE >>>>>>       m_PortIdentifyer.open("Modbus Serial Master", 
30000);
                        } catch (PortInUseException e) {
                          if(Modbus.debug) System.out.println(e.getMessage());

                          throw new Exception(e.getMessage());
                        }

I cannot understand why call m_PortIdentifyer.open("Modbus Serial Master", 
30000) terminates process (JVM) and doesn't throw exception...

Original issue reported on code.google.com by igor.zel...@gmail.com on 1 Sep 2013 at 6:10

GoogleCodeExporter commented 9 years ago
m_PortIdentifyer.open("Modbus Serial Master", 30000) crashes JVM if serial 
device file doesn't exist. Probably some defect in serial library...

I prepared small workaround for this issue.

Before calling m_PortIdentifyer.open("Modbus Serial Master", 30000) we need to 
check that device file exists in file system. One more important thing is that 
we need to check wherever it is Linux. Not sure about Windows - I don't have it.

It's pretty ugly (I added comment about it) but I don't see another way how to 
handle it...

So code (SerialConnectiom.java):

  public void open() throws Exception {
+   // If this is Linux then first of all we need to check that 
+   // device file exists. Otherwise call to m_PortIdentifyer.open()
+   // method will crash JVM.
+   // It is ugly patch but it is too late...
+   if (SystemUtils.IS_OS_LINUX) {
+       File portDevFile = new File(m_Parameters.getPortName());
+
+       if (!portDevFile.exists()) {
+           throw new Exception("Modbus serial device " + 
+               m_Parameters.getPortName() + " doesn't exist!");
+       }
+   }

I tested it trying to plug/unplug USB modbus master. Device unplugging doesn't 
crash Openhub. After plugging USB master - Openhub restores connection to it. 
So it works pretty well.

I cannot create my own server side clone of openhab 
(https://groups.google.com/forum/#!topic/openhab/fi6Y_O-2rok) so added patch 
file instead (see attachments).

How and to whom can I show it? 

P.S.
I'm not Java programmer - C++.

Original comment by igor.zel...@gmail.com on 2 Sep 2013 at 7:07

Attachments:

GoogleCodeExporter commented 9 years ago
Proposed patch is for Linux only.

If somebody uses modbus binding and USB rs485 (modbus) master under mac 
os/windows: check it please there as well.

For future:
If problem will occur under Mac OS then line: if (SystemUtils.IS_OS_LINUX) {
Should be replaced with: if (SystemUtils.IS_OS_UNIX) {
SystemUtils.IS_OS_UNIX covers both of Linux and Mac OS. Of course it will 
require testing. That is why I restricted it to Linux only.

If problem will occur under Windows then it will require separate workaround 
(check if USB device exist at the moment).

Original comment by igor.zel...@gmail.com on 2 Sep 2013 at 9:53

GoogleCodeExporter commented 9 years ago
This has been fixed with 1.3.0 with changeset 
https://code.google.com/p/openhab/source/detail?r=d5852603d140cba796afff1c6eac58
423ccdae3a

Original comment by kai.openhab on 14 Sep 2013 at 9:03