Use flock() to ensure exclusive access instead of TIOCEXCL
This commit is contained in:
parent
ed126f4235
commit
349f0adffb
|
@ -2,7 +2,7 @@
|
||||||
* SerialPort_Android.c
|
* SerialPort_Android.c
|
||||||
*
|
*
|
||||||
* Created on: Mar 13, 2015
|
* Created on: Mar 13, 2015
|
||||||
* Last Updated on: Jan 21, 2020
|
* Last Updated on: Feb 18, 2020
|
||||||
* Author: Will Hedgecock
|
* Author: Will Hedgecock
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012-2020 Fazecast, Inc.
|
* Copyright (C) 2012-2020 Fazecast, Inc.
|
||||||
|
@ -176,6 +176,7 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Close the port if there was a problem setting the parameters
|
// Close the port if there was a problem setting the parameters
|
||||||
|
tcdrain(serialPortFD);
|
||||||
while ((close(serialPortFD) == -1) && (errno != EBADF));
|
while ((close(serialPortFD) == -1) && (errno != EBADF));
|
||||||
serialPortFD = -1;
|
serialPortFD = -1;
|
||||||
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
||||||
|
@ -457,11 +458,9 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J
|
||||||
int numBytesAvailable = -1;
|
int numBytesAvailable = -1;
|
||||||
if ((serialPortFD > 0) && (ioctl(serialPortFD, FIONREAD, &numBytesAvailable) == -1))
|
if ((serialPortFD > 0) && (ioctl(serialPortFD, FIONREAD, &numBytesAvailable) == -1))
|
||||||
{
|
{
|
||||||
// Problem detected, allow others to open the port and close it ourselves
|
// Problem detected, close the port
|
||||||
ioctl(serialPortFD, TIOCNXCL);
|
|
||||||
tcdrain(serialPortFD);
|
tcdrain(serialPortFD);
|
||||||
while (((*env)->GetBooleanField(env, obj, isOpenedField)) && (close(serialPortFD) == -1) && (errno != EBADF));
|
while (((*env)->GetBooleanField(env, obj, isOpenedField)) && (close(serialPortFD) == -1) && (errno != EBADF));
|
||||||
serialPortFD = -1;
|
|
||||||
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
|
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
|
||||||
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
||||||
}
|
}
|
||||||
|
@ -579,8 +578,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
|
||||||
do { numBytesWritten = write(serialPortFD, writeBuffer+offset, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
|
do { numBytesWritten = write(serialPortFD, writeBuffer+offset, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
|
||||||
if ((numBytesWritten == -1) || ((numBytesWritten == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
if ((numBytesWritten == -1) || ((numBytesWritten == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
||||||
{
|
{
|
||||||
// Problem writing, allow others to open the port and close it ourselves
|
// Problem writing, close the port
|
||||||
ioctl(serialPortFD, TIOCNXCL);
|
|
||||||
ioctl(serialPortFD, TCSBRK, 1);
|
ioctl(serialPortFD, TCSBRK, 1);
|
||||||
while (((*env)->GetBooleanField(env, obj, isOpenedField)) && (close(serialPortFD) == -1) && (errno != EBADF));
|
while (((*env)->GetBooleanField(env, obj, isOpenedField)) && (close(serialPortFD) == -1) && (errno != EBADF));
|
||||||
serialPortFD = -1;
|
serialPortFD = -1;
|
||||||
|
@ -589,7 +587,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until all bytes were written in write-blocking mode
|
// Wait until all bytes were written in write-blocking mode
|
||||||
if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING) > 0)
|
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING) > 0) && (serialPortFD > 0))
|
||||||
ioctl(serialPortFD, TCSBRK, 1);
|
ioctl(serialPortFD, TCSBRK, 1);
|
||||||
|
|
||||||
// Return number of bytes written if successful
|
// Return number of bytes written if successful
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* SerialPort_Posix.c
|
* SerialPort_Posix.c
|
||||||
*
|
*
|
||||||
* Created on: Feb 25, 2012
|
* Created on: Feb 25, 2012
|
||||||
* Last Updated on: Jan 21, 2020
|
* Last Updated on: Feb 18, 2020
|
||||||
* Author: Will Hedgecock
|
* Author: Will Hedgecock
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012-2020 Fazecast, Inc.
|
* Copyright (C) 2012-2020 Fazecast, Inc.
|
||||||
|
@ -259,7 +259,7 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(
|
||||||
// Ensure that multiple root users cannot access the device simultaneously
|
// Ensure that multiple root users cannot access the device simultaneously
|
||||||
if (flock(serialPortFD, LOCK_EX | LOCK_NB) == -1)
|
if (flock(serialPortFD, LOCK_EX | LOCK_NB) == -1)
|
||||||
{
|
{
|
||||||
while ((close(serialPortFD) == -1) && (errno != EBADF));
|
while ((close(serialPortFD) == -1) && (errno == EINTR));
|
||||||
serialPortFD = -1;
|
serialPortFD = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -288,9 +288,8 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Close the port if there was a problem setting the parameters
|
// Close the port if there was a problem setting the parameters
|
||||||
ioctl(serialPortFD, TIOCNXCL);
|
|
||||||
tcdrain(serialPortFD);
|
tcdrain(serialPortFD);
|
||||||
while ((close(serialPortFD) == -1) && (errno != EBADF));
|
while ((close(serialPortFD) == -1) && (errno == EINTR));
|
||||||
serialPortFD = -1;
|
serialPortFD = -1;
|
||||||
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
||||||
}
|
}
|
||||||
|
@ -344,17 +343,14 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
|
||||||
options.c_iflag |= (INPCK | IGNPAR);
|
options.c_iflag |= (INPCK | IGNPAR);
|
||||||
options.c_iflag |= (XonXoffInEnabled | XonXoffOutEnabled);
|
options.c_iflag |= (XonXoffInEnabled | XonXoffOutEnabled);
|
||||||
|
|
||||||
// Set baud rate
|
// Set baud rate and apply changes
|
||||||
baud_rate baudRateCode = getBaudRateCode(baudRate);
|
baud_rate baudRateCode = getBaudRateCode(baudRate);
|
||||||
unsigned char nonStandardBaudRate = (baudRateCode == 0);
|
unsigned char nonStandardBaudRate = (baudRateCode == 0);
|
||||||
if (nonStandardBaudRate)
|
if (nonStandardBaudRate)
|
||||||
baudRateCode = B38400;
|
baudRateCode = B38400;
|
||||||
cfsetispeed(&options, baudRateCode);
|
cfsetispeed(&options, baudRateCode);
|
||||||
cfsetospeed(&options, baudRateCode);
|
cfsetospeed(&options, baudRateCode);
|
||||||
|
|
||||||
// Apply changes and block non-root users from opening this port
|
|
||||||
int retVal = configDisabled ? 0 : tcsetattr(serialPortFD, TCSANOW, &options);
|
int retVal = configDisabled ? 0 : tcsetattr(serialPortFD, TCSANOW, &options);
|
||||||
ioctl(serialPortFD, TIOCEXCL);
|
|
||||||
|
|
||||||
// Attempt to set the transmit buffer size and any necessary custom baud rates
|
// Attempt to set the transmit buffer size and any necessary custom baud rates
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
|
@ -514,11 +510,6 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
|
||||||
if (serialPortFD <= 0)
|
if (serialPortFD <= 0)
|
||||||
return JNI_TRUE;
|
return JNI_TRUE;
|
||||||
|
|
||||||
// Allow others to open the port
|
|
||||||
ioctl(serialPortFD, TIOCNXCL);
|
|
||||||
tcdrain(serialPortFD);
|
|
||||||
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
|
||||||
|
|
||||||
// Force the port to enter non-blocking mode to ensure that any current reads return
|
// Force the port to enter non-blocking mode to ensure that any current reads return
|
||||||
struct termios options = {0};
|
struct termios options = {0};
|
||||||
tcgetattr(serialPortFD, &options);
|
tcgetattr(serialPortFD, &options);
|
||||||
|
@ -528,37 +519,32 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
|
||||||
options.c_cc[VTIME] = 0;
|
options.c_cc[VTIME] = 0;
|
||||||
int retVal = fcntl(serialPortFD, F_SETFL, flags);
|
int retVal = fcntl(serialPortFD, F_SETFL, flags);
|
||||||
tcsetattr(serialPortFD, TCSANOW, &options);
|
tcsetattr(serialPortFD, TCSANOW, &options);
|
||||||
|
tcdrain(serialPortFD);
|
||||||
|
|
||||||
// Close the port
|
// Close the port
|
||||||
flock(serialPortFD, LOCK_UN);
|
flock(serialPortFD, LOCK_UN | LOCK_NB);
|
||||||
while ((close(serialPortFD) == -1) && (errno != EBADF));
|
while (((*env)->GetBooleanField(env, obj, isOpenedField)) && (close(serialPortFD) == -1) && (errno == EINTR))
|
||||||
|
errno = 0;
|
||||||
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
|
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
|
||||||
|
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
||||||
return JNI_TRUE;
|
return JNI_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj, jlong serialPortFD)
|
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(JNIEnv *env, jobject obj, jlong serialPortFD)
|
||||||
{
|
{
|
||||||
|
// Retrieve bytes available to read and close port upon error
|
||||||
int numBytesAvailable = -1;
|
int numBytesAvailable = -1;
|
||||||
if ((serialPortFD > 0) && (ioctl(serialPortFD, FIONREAD, &numBytesAvailable) == -1))
|
if ((serialPortFD > 0) && (ioctl(serialPortFD, FIONREAD, &numBytesAvailable) == -1))
|
||||||
{
|
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
||||||
// Problem detected, allow others to open the port and close it ourselves
|
|
||||||
ioctl(serialPortFD, TIOCNXCL);
|
|
||||||
tcdrain(serialPortFD);
|
|
||||||
while (((*env)->GetBooleanField(env, obj, isOpenedField)) && (close(serialPortFD) == -1) && (errno != EBADF));
|
|
||||||
serialPortFD = -1;
|
|
||||||
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
|
|
||||||
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return numBytesAvailable;
|
return numBytesAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWrite(JNIEnv *env, jobject obj, jlong serialPortFD)
|
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAwaitingWrite(JNIEnv *env, jobject obj, jlong serialPortFD)
|
||||||
{
|
{
|
||||||
|
// Retrieve bytes awaiting write and close port upon error
|
||||||
int numBytesToWrite = -1;
|
int numBytesToWrite = -1;
|
||||||
if (serialPortFD > 0)
|
if ((serialPortFD > 0) && (ioctl(serialPortFD, TIOCOUTQ, &numBytesToWrite) == -1))
|
||||||
ioctl(serialPortFD, TIOCOUTQ, &numBytesToWrite);
|
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
||||||
|
|
||||||
return numBytesToWrite;
|
return numBytesToWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,13 +567,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
|
||||||
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
|
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
|
||||||
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
||||||
{
|
{
|
||||||
// Problem reading, allow others to open the port and close it ourselves
|
// Problem reading, close the port
|
||||||
ioctl(serialPortFD, TIOCNXCL);
|
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
||||||
tcdrain(serialPortFD);
|
|
||||||
while (((*env)->GetBooleanField(env, obj, isOpenedField)) && (close(serialPortFD) == -1) && (errno != EBADF));
|
|
||||||
serialPortFD = -1;
|
|
||||||
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
|
|
||||||
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,13 +595,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
|
||||||
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
|
do { numBytesRead = read(serialPortFD, readBuffer+numBytesReadTotal, bytesRemaining); } while ((numBytesRead < 0) && (errno == EINTR));
|
||||||
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
||||||
{
|
{
|
||||||
// Problem reading, allow others to open the port and close it ourselves
|
// Problem reading, close the port
|
||||||
ioctl(serialPortFD, TIOCNXCL);
|
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
||||||
tcdrain(serialPortFD);
|
|
||||||
while (((*env)->GetBooleanField(env, obj, isOpenedField)) && (close(serialPortFD) == -1) && (errno != EBADF));
|
|
||||||
serialPortFD = -1;
|
|
||||||
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
|
|
||||||
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,13 +614,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
|
||||||
do { numBytesRead = read(serialPortFD, readBuffer, bytesToRead); } while ((numBytesRead < 0) && (errno == EINTR));
|
do { numBytesRead = read(serialPortFD, readBuffer, bytesToRead); } while ((numBytesRead < 0) && (errno == EINTR));
|
||||||
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
if ((numBytesRead == -1) || ((numBytesRead == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
||||||
{
|
{
|
||||||
// Problem reading, allow others to open the port and close it ourselves
|
// Problem reading, close the port
|
||||||
ioctl(serialPortFD, TIOCNXCL);
|
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
||||||
tcdrain(serialPortFD);
|
|
||||||
while (((*env)->GetBooleanField(env, obj, isOpenedField)) && (close(serialPortFD) == -1) && (errno != EBADF));
|
|
||||||
serialPortFD = -1;
|
|
||||||
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
|
|
||||||
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
numBytesReadTotal = numBytesRead;
|
numBytesReadTotal = numBytesRead;
|
||||||
|
@ -664,42 +635,19 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEn
|
||||||
jbyte *writeBuffer = (*env)->GetByteArrayElements(env, buffer, 0);
|
jbyte *writeBuffer = (*env)->GetByteArrayElements(env, buffer, 0);
|
||||||
int numBytesWritten, result = 0, ioctlResult = 0;
|
int numBytesWritten, result = 0, ioctlResult = 0;
|
||||||
|
|
||||||
// Set the DTR line to high if using RS-422
|
|
||||||
//ioctl(serialPortFD, TIOCMGET, &result);
|
|
||||||
//result |= TIOCM_DTR;
|
|
||||||
//ioctl(serialPortFD, TIOCMSET, &result);
|
|
||||||
|
|
||||||
// Write to port
|
// Write to port
|
||||||
do { numBytesWritten = write(serialPortFD, writeBuffer+offset, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
|
do { numBytesWritten = write(serialPortFD, writeBuffer+offset, bytesToWrite); } while ((numBytesWritten < 0) && (errno == EINTR));
|
||||||
if ((numBytesWritten == -1) || ((numBytesWritten == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
if ((numBytesWritten == -1) || ((numBytesWritten == 0) && (ioctl(serialPortFD, FIONREAD, &ioctlResult) == -1)))
|
||||||
{
|
{
|
||||||
// Problem writing, allow others to open the port and close it ourselves
|
// Problem writing, close the port
|
||||||
ioctl(serialPortFD, TIOCNXCL);
|
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
|
||||||
tcdrain(serialPortFD);
|
|
||||||
while (((*env)->GetBooleanField(env, obj, isOpenedField)) && (close(serialPortFD) == -1) && (errno != EBADF));
|
|
||||||
serialPortFD = -1;
|
serialPortFD = -1;
|
||||||
(*env)->SetLongField(env, obj, serialPortFdField, -1l);
|
|
||||||
(*env)->SetBooleanField(env, obj, isOpenedField, JNI_FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until all bytes were written in write-blocking mode
|
// Wait until all bytes were written in write-blocking mode
|
||||||
if ((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING) > 0)
|
if (((timeoutMode & com_fazecast_jSerialComm_SerialPort_TIMEOUT_WRITE_BLOCKING) > 0) && (serialPortFD > 0))
|
||||||
tcdrain(serialPortFD);
|
tcdrain(serialPortFD);
|
||||||
|
|
||||||
// Clear the DTR line if using RS-422
|
|
||||||
//#ifdef TIOCSERGETLSR
|
|
||||||
//do
|
|
||||||
//{
|
|
||||||
//result = ioctl(serialPortFD, TIOCSERGETLSR);
|
|
||||||
//if (result != TIOCSER_TEMT)
|
|
||||||
//usleep(100);
|
|
||||||
//} while (result != TIOCSER_TEMT);
|
|
||||||
//#endif
|
|
||||||
//ioctl(serialPortFD, TIOCMGET, &result);
|
|
||||||
//result &= ~TIOCM_DTR;
|
|
||||||
//ioctl(serialPortFD, TIOCMSET, &result);
|
|
||||||
//do { result = tcflush(serialPortFD, TCIFLUSH); } while ((result < 0) && (errno == EINTR));
|
|
||||||
|
|
||||||
// Return number of bytes written if successful
|
// Return number of bytes written if successful
|
||||||
(*env)->ReleaseByteArrayElements(env, buffer, writeBuffer, JNI_ABORT);
|
(*env)->ReleaseByteArrayElements(env, buffer, writeBuffer, JNI_ABORT);
|
||||||
return numBytesWritten;
|
return numBytesWritten;
|
||||||
|
|
Loading…
Reference in New Issue