LeaveCriticalSection有BUG?

偶然发现Windows API函数LeaveCriticalSection存在一个问题,那就是在调用它离开临界区时,会把临界区引用计数减一,而不判断当前线程是不是拥有该临界区,这样就可能引发问题,比如A线程拥有该临界区,但B线程可以调用LeaveCriticalSection来使得其它等待该临界区的线程拥有该临界区,或者调用LeaveCriticalSection次数大于EnterCriticalSection的次数也可能出现误操作而导致不可预知的后果。

把EnterCriticalSection换下面这一段代码可以有效的防止占用锁的线程已经退出而导致死锁的情况(亲测有效):

//尝试进入临界区
while(!TryEnterCriticalSection(&moSection)){
	//进入失败,判断当前占有临界区的线程是否还存活
	if(aoSection.RecursionCount > 0){
		DWORD result = WaitForSingleObject(aoSection.OwningThread, 0);
		if(result == WAIT_FAILED){
			//如果线程已经退出,则代表线程被异常结束或代码问题导致锁没有释放,就利用此bug强制释放锁
			while(aoSection.RecursionCount > 0){
				LeaveCriticalSection(&moSection);
			}	
		}
	}
}



#include<stdio.h> #include<windows.h> #include"structdef.h" #include"calculatefun.h" #include"recv_thread.h" DWORD WINAPI slove(LPVOID lpParam) { while (1) { WaitForSingleObject(hDataReady, INFINITE); EnterCriticalSection(&g_cs); int packet_length = (packet->MessageHeader.Messagelength); printf("packet_length:%d", packet_length); if (packet->MessageHeader.Messagelength == sizeof(simulaterecv_shangweiji)) { printf("1:%d\n", packet->MessageHeader.Messagelength); printf("2:%d\n", sizeof(simulaterecv_shangweiji)); Target a[32]; for (int i = 0; i < 32; i++) { a[i].Target_Speed = packet->shuju.Point_Speed[i]; a[i].Target_Position = packet->shuju.Point_Distance[i]; a[i].attenuation = packet->shuju.Point_Gain_points[i]; a[i].target_interval = packet->shuju.Point_PulseInterval[i]; a[i].Target_Acceleration = packet->shuju.Point_JSD[i]; } ThreadResult b; b = calculate(a, packet->shuju.number); /*send_fpga*/ printf("Enable:%d\n", packet->shuju.En_1); for (int i = 0; i < 10; i++) printf("calculate0Speed:%f\n", b.g_Speed_points[0][i]); for (int i = 0; i < 10; i++) printf("calculate0Position:%f\n", b.g_Distance_points[0][i]); for (int i = 0; i < 10; i++) printf("calculate1Speed:%f\n", b.g_Speed_points[1][i]); for (int i = 0; i < 10; i++) printf("calculate1Position:%f\n", b.g_Distance_points[1][i]); for (int i = 0; i < 10; i++) printf("Gain:%d\n", packet->shuju.Point_Gain_points[i]); for (int i = 0; i < 32; i++) printf("swerling:%d\n",packet->shuju.Point_SwerlingMode[i]); //free(packet); Sleep(100); Sleep(100); Sleep(100); free(packet); LeaveCriticalSection(&g_cs); SetEvent(hProcessDone); } else if ((disturbrecv_shangweiji*)packet->MessageHeader.Messagelength == sizeof(disturbrecv_shangweiji)) { printf("1:%d\n", (disturbrecv_shangweiji*)packet->MessageHeader.Messagelength); printf("2:%d\n", sizeof(simulaterecv_shangweiji)); LeaveCriticalSection(&g_cs); printf("disturb\n"); SetEvent(hProcessDone); } } }当为目标模拟时,计算结果时,如何设计一个能一直caclucate的方案,如果位置<0就要停止,不再计算
最新发布
04-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值