gpt4 book ai didi

java - CloseHandle((Handle)端口)没有返回

转载 作者:行者123 更新时间:2023-12-02 09:36:53 26 4
gpt4 key购买 nike

我的 .dll 中的 windows closeHandle((Handle)port) 函数存在问题。它没有回来。该问题每隔几个小时就会发生一次。

使用.dll的java应用程序连接、读取和写入数据。 java 应用程序执行的最后一个方法调用是写入数据,并立即调用释放方法,该方法调用 JNI 中的 closeHandle 函数。

CloseHandle 是否未返回,因为写入仍在进行?当 closeHandle 挂起/不返回时,有没有办法优雅地恢复正常。提前致谢。

附上调用closeHandle的函数代码。

{
HANDLE port;
jfieldID portFID = GetFieldId(env, jthis, "portnbr", "J");
if ( portFID == 0 ){
flog("ERROR: Java_com_hctsi_comm_Serial_close() portFID=0\n");
return;
}
port = (HANDLE)env->GetLongField(jthis, portFID);
if ( 0 != port ) {
flog("Java_com_hctsi_comm_Serial_close() port %d\n", port);
int count = 0;
while ( !CloseHandle((HANDLE)port) && count < 10 ) {
flog("ERROR Java_com_hctsi_comm_Serial_close() closeHandle failed with an error %d\n", count, port, GetLastError);
flog("ERROR Java_com_hctsi_comm_Serial_close() failed count %d port %d\n", count, port);
count++;
Sleep(1000);
}
env->SetLongField(jthis, portFID, (jlong)0);
}
CloseLog();
} `

The code to open a port is below

`JNIEXPORT jint JNICALL Java_com_hctsi_comm_Serial_open(JNIEnv *env, jobject jthis, jstring jportName, jint baud, jbyte dataBits, jchar parity, jbyte stop, jchar flowin, jchar flowout, jchar rts, jchar cts, jchar dtr, jchar dsr, jint usTimeout)
{
int result;
jboolean iscopy;
HANDLE port;

StartLog();
const char *portName = env->GetStringUTFChars(jportName, &iscopy);
flog("serial port open %s baud %d data %d parity %c stop %d\n", portName, baud, dataBits, parity, stop);


// ================ DEBUG ======================================================
/*
{
jclass thisClass;
if (! (thisClass = env->GetObjectClass(jthis))) {
flog("GetFieldId thisClass=NULL\n");
return (0);
}
jmethodID getComPort = env->JNIEnv_::GetMethodID(thisClass, "getComPort", "()Ljava/lang/String;");
jfieldID tempFID = GetFieldId(env, jthis, "comPort", "Ljava/lang/String;");
flog(" getComPort=%d\n",getComPort);
flog(" comPort=%d\n",tempFID);
}
*/
// ================ DEBUG ======================================================

jfieldID portFID = GetFieldId(env, jthis, "portnbr", "J");
flog(" portFID=%d\n",portFID);
if (portFID == 0) {
flog("ERROR: Java_com_hctsi_comm_Serial_open() portFID=0\n");
return (jint)-1;
}
port = (HANDLE)env->GetLongField(jthis, portFID);
if (0 != port) {
flog("ERROR: Java_com_hctsi_comm_Serial_open() port %d\n", port);
CloseHandle((HANDLE)port);
}
port = (HANDLE)serOpen((char *)portName, baud, dataBits, parity, stop, flowin, flowout, rts, cts, dtr, dsr, usTimeout);
if (port != NULL) {
result = (jint)1;
} else {
errCode = GetLastError();
flog("Java_com_hctsi_comm_Serial_open() port %d, errorcode=%d\n", port, errCode);
result = (jint)-1;
}
flog("Java_com_hctsi_comm_Serial_open() port %d\n", port);
env->SetLongField(jthis, portFID, (jlong)port);
return(jint)result;
} `


最佳答案

当您调用 CloseHandle() 函数时,Windows 内部会将其转换为 IRP_MJ_CLOSE 设备控制代码,并使用该控制代码调用设备驱动程序。之后,由设备驱动程序关闭所有操作并将状态代码返回给调用者。

写得不好的串行端口驱动程序(可能正在等待锁被释放,或者等待操作完成,或者做不应该做的事情)将阻止调用并阻止它返回到调用者。正如您推测的那样,写入操作很可能仍在发生,而驱动程序只是在等待操作完成。真正应该发生的是串行端口驱动程序应该中止所有操作并立即关闭并返回调用。但谁知道驱动是怎么写的呢。

如果您想找出答案,可以将内核调试器附加到串行端口驱动程序并拦截 IRP_MJ_CLOSE,这将为您提供答案。

我在代码中注意到的另一件事是,如果 CloseHandle() 返回错误,您将尝试关闭端口。这不是正确的处理方式。既然第一次关闭句柄失败,为什么你期望下次调用时关闭成功呢?除非驱动程序编写者有充分记录,如果 CloseHandle() 失败,您应该再次调用它最多 10 次,否则我会立即记录关闭失败并返回。

关于java - CloseHandle((Handle)端口)没有返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57435800/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com