[√]window下子线程CCLOG导致主线程阻塞问题

简介: [√]window下子线程CCLOG导致主线程阻塞问题

windbg wdk下载

下载地址,安装的时候选择Debugging Tools For Windows即可

image.png

windbg 使用

通过File/Attach to a process快捷键F6附加到已经阻塞的程序中

查看所有线程的堆栈信息

~*kb

  • k*  命令显示给定线程的堆栈帧以及相关信息。
  • b选项显示传递给堆栈跟踪中每个函数的前三个参数。

image.png

vs的线程情况

可以看到在这里加锁时,因为被其他线程锁定了,其他线程并没有解锁,就导致这里被阻塞了

image.png

f

!cs -l 仅显示死锁的临界区信息。

相关的的线程锁函数

NtWaitForAlertByThreadId

NtWaitForAlertByThreadId 是在 Windows 操作系统中的 ntdll.dll 动态链接库中定义的函数,用于等待指定线程的警告状态。

该函数的原型如下:

cCopy Code
NTSTATUS NtWaitForAlertByThreadId(
  HANDLE     ThreadHandle,
  PLARGE_INTEGER Timeout
);
  • ThreadHandle:要等待的线程句柄。
  • Timeout:等待的超时时间。

该函数的作用是使当前线程进入等待状态,直到所指定的线程发出警告通知。警告通常由应用程序自定义的机制触发。

出现在调用堆栈中的 NtWaitForAlertByThreadId 表明当前线程正在等待指定线程发出的警告。

WaitForMultipleObjects

DWORD WaitForMultipleObjects(
  [in] DWORD        nCount,
  [in] const HANDLE *lpHandles,
  [in] BOOL         bWaitAll,
  [in] DWORD        dwMilliseconds
);
2  Id: 2568.4a78 Suspend: 1 Teb: 01bcc000 Unfrozen
#  ChildEBP RetAddr  Args to Child              
00 05cffcf4 75b13033 00000003 05830bf0  00000001 ntdll!NtWaitForMultipleObjects+0xc
                     nCount   lpHandles bWaitAll # 对应的参数
# 第二个参数是个指针,通过dd查看指针指向的内存数据
:003> dd 05830bf0 
05830bf0  00000510 00000518 0000051c 00000000
05830c00  05830c30 00000000 00000000 00000000
05830c10  00000000 00000000 00000000 00000000
05830c20  00000000 00000000 00000000 00000000
05830c30  05830c60 00000000 00000000 00000000
05830c40  00000000 00000000 00000000 00000000
05830c50  00000000 00000000 00000000 00000000
05830c60  05830c90 00000000 00000000 00000000
0:003> !cs 05830bf0 
-----------------------------------------
Critical section   = 0x05830bf0 (+0x5830BF0)
DebugInfo          = 0x00000510
LOCKED
LockCount          = 0xFFFFFEB9  # 这是一个负数
WaiterWoken        = Yes
OwningThread       = 0x00000000 # 没有线程拥有它
RecursionCount     = 0x51C
LockSemaphore      = 0x5830C30
SpinCount          = 0x00000000

WaitForSingleObject

DWORD WaitForSingleObject(
  [in] HANDLE hHandle,
  [in] DWORD  dwMilliseconds
);

最终问题定位

程序就是出现了死锁,死锁的原因是window窗口部分代码导致的,子线程调用Windows的SendMessage,导致的主线程阻塞,网上说SendMessage里面其实有一个锁,有这种可能导致主线程阻塞。

CCLOG函数在win32上的实现,里面有调用SendMessage,而我在子线程里面打log,触发了这个大坑

解决办法是MsgWaitForMultipleObjects(),但是我不清楚怎么处理,对Windows编程不太熟悉,这也算是cocos2dx的一个bug

目录
相关文章
|
8月前
|
Java 数据库 Android开发
【专栏】Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理
【4月更文挑战第27天】本文探讨了Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理。通过案例分析展示了网络请求、图像处理和数据库操作的优化实践。同时,文章指出并发编程的挑战,如性能评估、调试及兼容性问题,并强调了多线程优化对提升应用性能的重要性。开发者应持续学习和探索新的优化策略,以适应移动应用市场的竞争需求。
209 5
|
安全 Java
【JavaSE专栏76】三态和五态,线程的不同状态:新建、运行、状态、阻塞、等待、计时等待状态
【JavaSE专栏76】三态和五态,线程的不同状态:新建、运行、状态、阻塞、等待、计时等待状态
119 0
|
10天前
|
Java API 调度
【JavaEE】——多线程(join阻塞,计算,引用,状态)
【JavaEE】——多线程,join,sleep引起的线程阻塞,多线程提升计算效率,如何获取线程的引用和状态
|
8月前
|
消息中间件 Linux 调度
【Linux 进程/线程状态 】深入理解Linux C++中的进程/线程状态:阻塞,休眠,僵死
【Linux 进程/线程状态 】深入理解Linux C++中的进程/线程状态:阻塞,休眠,僵死
595 0
【多线程面试题十二】、阻塞线程的方式有哪些?
线程阻塞的方式包括调用sleep()方法、阻塞式IO操作、等待同步监视器的获取、等待通知(notify),以及慎用的suspend()方法。
【多线程面试题十一】、如何实现子线程先执行,主线程再执行?
要实现子线程先执行,主线程再执行,可以在启动子线程后立即调用其join()方法,使主线程等待子线程执行完成。
|
7月前
|
前端开发 JavaScript
JavaScript异步处理避免了单线程阻塞,如回调函数、Promise和async/await。
【6月更文挑战第22天】JavaScript异步处理避免了单线程阻塞,如回调函数、Promise和async/await。回调是基础,用于在操作完成后执行函数;Promise管理异步状态,支持链式调用;async/await提供同步代码外观,简化错误处理。每种技术在处理耗时任务时都起着关键作用。
62 3
|
7月前
|
Java
【技术解码】Java线程的五味人生:新建、就绪、运行、阻塞与死亡的哲学解读!
【6月更文挑战第19天】Java线程生命周期如同人生旅程,经历新建、就绪、运行、阻塞至死亡五阶段。从`new Thread()`的诞生到`start()`的蓄势待发,再到`run()`的全力以赴,线程在代码中奔跑。阻塞时面临挑战,等待资源释放,最终通过`join()`或中断结束生命。线程的每个状态转变,都是编程世界与哲思的交汇点。
51 1
|
8月前
|
设计模式 安全 Java
Java 多线程系列Ⅳ(单例模式+阻塞式队列+定时器+线程池)
Java 多线程系列Ⅳ(单例模式+阻塞式队列+定时器+线程池)
|
8月前
|
前端开发 JavaScript UED
由于JavaScript是单线程的,因此在处理大量异步操作时,需要确保不会阻塞UI线程
【5月更文挑战第13天】JavaScript中的Promise和async/await常用于处理游戏开发中的异步操作,如加载资源、网络请求和动画帧更新。Promise表示异步操作的结果,通过.then()和.catch()处理回调。async/await作为Promise的语法糖,使异步代码更简洁,类似同步代码。在游戏循环中,使用async/await可清晰管理资源加载和更新,但需注意避免阻塞UI线程,并妥善处理加载顺序、错误和资源管理,以保证游戏性能和稳定性。
75 3