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

Reconnect problem #101

Open NefiLL opened 7 years ago

NefiLL commented 7 years ago

My problem is as follows: I am working with two devices on separate COM ports. I am trying to implement reconnect method, and I came across the following problem: I pulled out from the USB port one of the connected device and I called out 'open' method on closed SerialPort after putting the usb in again. This operation freezes all connections for about 3-4 seconds, until connection has been renewed. It looks like blocking is in this line(CommPortIdentifier ->getPortIdentifier(String portName)): jtermios.JTermios.open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK);

It is not a problem for me that reconnect takes so long .The problem is to freeze all connections when the port is reopened. I note that this situation only occurs when the USB cable is unexpectedly pulled out. Is it possible to solve this problem?. I will be grateful for the help.

My reconnect method: protected purejavacomm.SerialPort reconnect(String portName) throws Exception { pjcSerialPort = (purejavacomm.SerialPort) CommPortIdentifier.getPortIdentifier(portName).open(portName, 2000); pjcSerialPort.setSerialPortParams(serialParameters.getBaudRade(), serialParameters.getDataBits(), serialParameters.getStopBits(), serialParameters.getParity()); pjcSerialPort.setFlowControlMode(serialParameters.getFlowControl()); return pjcSerialPort; }

nyholku commented 7 years ago

Actually I think it hangs inside jtermios.JTermios.open, somewhere in jtermios.windows.JTermiosImpl.java.open(), so you should trace where it actually hangs.

However, I think it will hang in a call to WinAPI so doubt there is nothing that can be done in this situation as there would appear to be nothing inside PureJavaComm that could cause freezing of all connections.

NefiLL commented 7 years ago

Thank you for the quick reply. I traced the code and it happens exactly on line 128 in 'jtermios.windows.JTermiosImpl' : synchronized (JTermiosImpl.this) .

nyholku commented 7 years ago

Ok, well, that is interesting and more hopeful. So two or more threads are accessing the same port in synchronised method. This is most likely something to do with your code as there is only one thread per port inside PJC. So you should run the system under debugger and when you manage to cause the 'everything freezes' condition pause all threads and find out what threads are accessing the port at the same time, i.e. what/who is preventing open() to enter the synchronised block at line 128

NefiLL commented 7 years ago

Here is the very simple test code : https://pastebin.com/pTWTSjUZ. The problem occurs when in the main method I start two threads simultaneously (startThreads method). In case I have created two classes with separate threads for each device and start them separately (one by one, not in CustomTest class) then the problem does not occur, restarting one connection does not interfere with the other. In the near future I should have a little more time to look at it.

NefiLL commented 7 years ago

Can you explain why "open" and "close" methods are not synchronized? Why do you synchronize an instance of a class in these two cases? (Synchronized (JTermiosImpl.this)). I have commented the synchronization of the instance of the class, and i have marked the methods 'open' and 'close' as synchronous, then everything is fine and there is no problem during restart.

nyholku commented 7 years ago

'JTermiosImpl.this' is same as 'this' and thus should have the same effect AFAIU as making the method itself synchronised. Which of those three to use is a matter of style and I don't recall offhand what was my motivation, probably I chose to do that inside the method because the signature of open/close in the JTermios class does not contain synchronized. So why it makes a difference which way you do this is a mystery.