Synchronize open/close on class as well as instance

This commit is contained in:
Will Hedgecock 2021-11-19 12:44:28 -06:00
parent bcc9e1e19f
commit b52271c48c
2 changed files with 62 additions and 54 deletions

View File

@ -7,7 +7,7 @@ buildscript {
plugins { plugins {
id 'maven-publish' id 'maven-publish'
id 'biz.aQute.bnd.builder' version '5.0.0' id 'biz.aQute.bnd.builder' version '6.0.0'
} }
group = 'com.fazecast' group = 'com.fazecast'

View File

@ -2,7 +2,7 @@
* SerialPort.java * SerialPort.java
* *
* Created on: Feb 25, 2012 * Created on: Feb 25, 2012
* Last Updated on: Nov 12, 2021 * Last Updated on: Nov 19, 2021
* Author: Will Hedgecock * Author: Will Hedgecock
* *
* Copyright (C) 2012-2021 Fazecast, Inc. * Copyright (C) 2012-2021 Fazecast, Inc.
@ -418,56 +418,60 @@ public final class SerialPort
*/ */
public final synchronized boolean openPort(int safetySleepTime, int deviceSendQueueSize, int deviceReceiveQueueSize) public final synchronized boolean openPort(int safetySleepTime, int deviceSendQueueSize, int deviceReceiveQueueSize)
{ {
// Set the send/receive internal buffer sizes, and return true if already opened // Synchronize this method to the class scope as well
safetySleepTimeMS = safetySleepTime; synchronized (SerialPort.class)
sendDeviceQueueSize = deviceSendQueueSize; {
receiveDeviceQueueSize = deviceReceiveQueueSize; // Set the send/receive internal buffer sizes, and return true if already opened
if (portHandle > 0) safetySleepTimeMS = safetySleepTime;
return configPort(portHandle); sendDeviceQueueSize = deviceSendQueueSize;
receiveDeviceQueueSize = deviceReceiveQueueSize;
// Force a sleep to ensure that the port does not become unusable due to rapid closing/opening on the part of the user if (portHandle > 0)
if (safetySleepTimeMS > 0) return configPort(portHandle);
try { Thread.sleep(safetySleepTimeMS); } catch (Exception e) { Thread.currentThread().interrupt(); }
// Force a sleep to ensure that the port does not become unusable due to rapid closing/opening on the part of the user
// If this is an Android root application, we must explicitly allow serial port access to the library if (safetySleepTimeMS > 0)
File portFile = isAndroid ? new File(comPort) : null; try { Thread.sleep(safetySleepTimeMS); } catch (Exception e) { Thread.currentThread().interrupt(); }
if (portFile != null && (!portFile.canRead() || !portFile.canWrite()))
{ // If this is an Android root application, we must explicitly allow serial port access to the library
Process process = null; File portFile = isAndroid ? new File(comPort) : null;
try if (portFile != null && (!portFile.canRead() || !portFile.canWrite()))
{ {
process = Runtime.getRuntime().exec("su"); Process process = null;
DataOutputStream writer = new DataOutputStream(process.getOutputStream()); try
writer.writeBytes("chmod 666 " + comPort + "\n"); {
writer.writeBytes("exit\n"); process = Runtime.getRuntime().exec("su");
writer.flush(); DataOutputStream writer = new DataOutputStream(process.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); writer.writeBytes("chmod 666 " + comPort + "\n");
while (reader.readLine() != null); writer.writeBytes("exit\n");
} writer.flush();
catch (Exception e) BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
{ while (reader.readLine() != null);
e.printStackTrace(); }
return false; catch (Exception e)
} {
finally e.printStackTrace();
{
if (process == null)
return false; return false;
try { process.waitFor(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } }
try { process.getInputStream().close(); } catch (IOException e) { e.printStackTrace(); return false; } finally
try { process.getOutputStream().close(); } catch (IOException e) { e.printStackTrace(); return false; } {
try { process.getErrorStream().close(); } catch (IOException e) { e.printStackTrace(); return false; } if (process == null)
try { Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } return false;
try { process.waitFor(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; }
try { process.getInputStream().close(); } catch (IOException e) { e.printStackTrace(); return false; }
try { process.getOutputStream().close(); } catch (IOException e) { e.printStackTrace(); return false; }
try { process.getErrorStream().close(); } catch (IOException e) { e.printStackTrace(); return false; }
try { Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; }
}
} }
}
// Open the serial port and start an event-based listener if registered
// Open the serial port and start an event-based listener if registered if ((portHandle = openPortNative()) > 0)
if ((portHandle = openPortNative()) > 0) {
{ if (serialEventListener != null)
if (serialEventListener != null) serialEventListener.startListening();
serialEventListener.startListening(); }
} return (portHandle > 0);
return (portHandle > 0); }
} }
/** /**
@ -504,11 +508,15 @@ public final class SerialPort
*/ */
public final synchronized boolean closePort() public final synchronized boolean closePort()
{ {
if (serialEventListener != null) // Synchronize this method to the class scope as well
serialEventListener.stopListening(); synchronized (SerialPort.class)
if (portHandle > 0) {
portHandle = closePortNative(portHandle); if (serialEventListener != null)
return (portHandle < 0); serialEventListener.stopListening();
if (portHandle > 0)
portHandle = closePortNative(portHandle);
return (portHandle < 0);
}
} }
/** /**