Fixed JNI crash when calling native functions after port has already closed.

This commit is contained in:
hedgecrw85 2015-03-16 10:11:06 -05:00
parent 56586964d4
commit 7993eeb7a0
3 changed files with 40 additions and 4 deletions

View File

@ -101,6 +101,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
struct serial_struct serialInfo;
jclass serialCommClass = env->GetObjectClass(obj);
int portFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (portFD <= 0)
return JNI_FALSE;
// Set raw-mode to allow the use of tcsetattr() and ioctl()
fcntl(portFD, F_SETFL, 0);
@ -146,6 +148,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo
struct termios options;
jclass serialCommClass = env->GetObjectClass(obj);
int portFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (portFD <= 0)
return JNI_FALSE;
// Get port parameters from Java class
int flowControl = env->GetIntField(obj, env->GetFieldID(serialCommClass, "flowControl", "I"));
@ -175,6 +179,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
int serialFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
int timeoutMode = env->GetIntField(obj, env->GetFieldID(serialCommClass, "timeoutMode", "I"));
int readTimeout = env->GetIntField(obj, env->GetFieldID(serialCommClass, "readTimeout", "I"));
if (serialFD <= 0)
return JNI_FALSE;
// Retrieve existing port configuration
struct termios options;
@ -222,6 +228,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
{
jclass serialCommClass = env->GetObjectClass(obj);
int serialFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialFD <= 0)
return JNI_FALSE;
// Get event flags from Java class
int eventsToMonitor = env->GetIntField(obj, env->GetFieldID(serialCommClass, "eventFlags", "I"));
@ -249,6 +257,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
{
jclass serialCommClass = env->GetObjectClass(obj);
int serialFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialFD <= 0)
return 0;
// Initialize the waiting set and the timeouts
struct timeval timeout = { 1, 0 };
@ -267,6 +277,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
{
// Close port
int portFD = (int)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
if (portFD <= 0)
return JNI_TRUE;
close(portFD);
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), -1l);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
@ -279,7 +291,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J
int serialPortFD = (int)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
int numBytesAvailable = -1;
if (serialPortFD != -1)
if (serialPortFD > 0)
ioctl(serialPortFD, FIONREAD, &numBytesAvailable);
return numBytesAvailable;

View File

@ -116,6 +116,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
struct termios options;
jclass serialCommClass = env->GetObjectClass(obj);
int portFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (portFD <= 0)
return JNI_FALSE;
// Set raw-mode to allow the use of tcsetattr() and ioctl()
fcntl(portFD, F_SETFL, 0);
@ -152,6 +154,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo
struct termios options;
jclass serialCommClass = env->GetObjectClass(obj);
int portFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (portFD <= 0)
return JNI_FALSE;
// Get port parameters from Java class
int flowControl = env->GetIntField(obj, env->GetFieldID(serialCommClass, "flowControl", "I"));
@ -181,6 +185,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
int serialFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
int timeoutMode = env->GetIntField(obj, env->GetFieldID(serialCommClass, "timeoutMode", "I"));
int readTimeout = env->GetIntField(obj, env->GetFieldID(serialCommClass, "readTimeout", "I"));
if (serialFD <= 0)
return JNI_FALSE;
// Retrieve existing port configuration
struct termios options;
@ -228,6 +234,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
{
jclass serialCommClass = env->GetObjectClass(obj);
int serialFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialFD <= 0)
return JNI_FALSE;
// Get event flags from Java class
int eventsToMonitor = env->GetIntField(obj, env->GetFieldID(serialCommClass, "eventFlags", "I"));
@ -255,6 +263,8 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
{
jclass serialCommClass = env->GetObjectClass(obj);
int serialFD = (int)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialFD <= 0)
return 0;
// Initialize the waiting set and the timeouts
struct timeval timeout = { 1, 0 };
@ -273,6 +283,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
{
// Close port
int portFD = (int)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
if (portFD <= 0)
return JNI_TRUE;
close(portFD);
env->SetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"), -1l);
env->SetBooleanField(obj, env->GetFieldID(env->GetObjectClass(obj), "isOpened", "Z"), JNI_FALSE);
@ -285,7 +297,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_bytesAvailable(J
int serialPortFD = (int)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
int numBytesAvailable = -1;
if (serialPortFD != -1)
if (serialPortFD > 0)
ioctl(serialPortFD, FIONREAD, &numBytesAvailable);
return numBytesAvailable;

View File

@ -223,9 +223,11 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configPort(J
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(DCB);
jclass serialCommClass = env->GetObjectClass(obj);
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return JNI_FALSE;
// Get port parameters from Java class
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
DWORD baudRate = (DWORD)env->GetIntField(obj, env->GetFieldID(serialCommClass, "baudRate", "I"));
BYTE byteSize = (BYTE)env->GetIntField(obj, env->GetFieldID(serialCommClass, "dataBits", "I"));
int stopBitsInt = env->GetIntField(obj, env->GetFieldID(serialCommClass, "stopBits", "I"));
@ -257,6 +259,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configFlowCo
dcbSerialParams.DCBlength = sizeof(DCB);
jclass serialCommClass = env->GetObjectClass(obj);
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return JNI_FALSE;
// Get flow control parameters from Java class
int flowControl = env->GetIntField(obj, env->GetFieldID(serialCommClass, "flowControl", "I"));
@ -303,6 +307,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configTimeou
int timeoutMode = env->GetIntField(obj, env->GetFieldID(serialCommClass, "timeoutMode", "I"));
DWORD readTimeout = (DWORD)env->GetIntField(obj, env->GetFieldID(serialCommClass, "readTimeout", "I"));
DWORD writeTimeout = (DWORD)env->GetIntField(obj, env->GetFieldID(serialCommClass, "writeTimeout", "I"));
if (serialHandle == INVALID_HANDLE_VALUE)
return JNI_FALSE;
// Set updated port timeouts
timeouts.WriteTotalTimeoutMultiplier = 0;
@ -361,6 +367,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_configEventF
{
jclass serialCommClass = env->GetObjectClass(obj);
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return JNI_FALSE;
// Get event flags from Java class
int eventsToMonitor = env->GetIntField(obj, env->GetFieldID(serialCommClass, "eventFlags", "I"));
@ -393,12 +401,14 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
{
jclass serialCommClass = env->GetObjectClass(obj);
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(serialCommClass, "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return 0;
OVERLAPPED overlappedStruct = {0};
overlappedStruct.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (overlappedStruct.hEvent == NULL)
{
CloseHandle(overlappedStruct.hEvent);
return -1;
return 0;
}
// Wait for a serial port event
@ -427,6 +437,8 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
{
// Purge any outstanding port operations
HANDLE serialPortHandle = (HANDLE)env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "portHandle", "J"));
if (serialPortHandle == INVALID_HANDLE_VALUE)
return JNI_TRUE;
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
// Close port