linux read 死锁,linux下记一次使用gdb死锁问题的定位以及pthread_cancel使用的建议

程序跑死卡住了,怀疑是死锁引起的

使用

gdb attach pid

命令附加到那个进程上,然后再gdb里输入命令

info thread

得到如下信息

(gdb) info thread

Id Target Id Frame

4 Thread 0x7f466b8e1700 (LWP 10945) "jtnvragentserve" 0x00007f466cbd5b13 in epoll_wait () at ../sysdeps/unix/syscall-template.S:81

3 Thread 0x7f466c0e2700 (LWP 11009) "jtnvragentserve" 0x00007f466cbccda3 in select () at ../sysdeps/unix/syscall-template.S:81

2 Thread 0x7f4653fff700 (LWP 9171) "jtnvragentserve" __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135

* 1 Thread 0x7f466e052780 (LWP 10942) "jtnvragentserve" __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135

很明显,线程9171和10942确实是死锁了,

再使用命令查看线程堆栈信息

thread apply all bt

看到如下信息

(gdb) thread apply all bt

Thread 4 (Thread 0x7f466b8e1700 (LWP 10945)):

#0 0x00007f466cbd5b13 in epoll_wait () at ../sysdeps/unix/syscall-template.S:81

#1 0x00007f466c38ed88 in ?? ()

#2 0x00007f465c000f80 in ?? ()

#3 0xffffffff64001c50 in ?? ()

#4 0x000000007fffffff in ?? ()

#5 0x0000000000000000 in ?? ()

Thread 3 (Thread 0x7f466c0e2700 (LWP 11009)):

#0 0x00007f466cbccda3 in select () at ../sysdeps/unix/syscall-template.S:81

#1 0x0000000000455373 in _eXosip_read_message (excontext=0x144f770, max_message_nb=1, sec_max=1, usec_max=0) at udp.c:1580

#2 0x00000000004415a4 in eXosip_execute (excontext=0x144f770) at eXconf.c:791

#3 0x000000000044254e in _eXosip_thread (arg=0x144f770) at eXconf.c:1090

#4 0x00007f466d9b8182 in start_thread (arg=0x7f466c0e2700) at pthread_create.c:312

#5 0x00007f466cbd547d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Thread 2 (Thread 0x7f4653fff700 (LWP 9171)):

#0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135

#1 0x00007f466d9ba657 in _L_lock_909 () from /lib/x86_64-linux-gnu/libpthread.so.0

#2 0x00007f466d9ba480 in __GI___pthread_mutex_lock (mutex=0x1e34140) at ../nptl/pthread_mutex_lock.c:79

#3 0x00000000004d95be in jthread::JMutex::Lock() ()

#4 0x00000000004e9013 in jrtplib::RTPUDPv4Transmitter::WaitForIncomingData(jrtplib::RTPTime const&, bool*) ()

#5 0x000000000050789c in jrtplib::RTPPollThread::Thread() ()

#6 0x00000000004d9b67 in jthread::JThread::TheThread(void*) ()

#7 0x00007f466d9b8182 in start_thread (arg=0x7f4653fff700) at pthread_create.c:312

#8 0x00007f466cbd547d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Thread 1 (Thread 0x7f466e052780 (LWP 10942)):

#0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135

#1 0x00007f466d9ba657 in _L_lock_909 () from /lib/x86_64-linux-gnu/libpthread.so.0

#2 0x00007f466d9ba480 in __GI___pthread_mutex_lock (mutex=0x1e34140) at ../nptl/pthread_mutex_lock.c:79

#3 0x00000000004d95be in jthread::JMutex::Lock() ()

#4 0x00000000004e9263 in jrtplib::RTPUDPv4Transmitter::AbortWait() ()

#5 0x0000000000507645 in jrtplib::RTPPollThread::Stop() ()

#6 0x000000000050748b in jrtplib::RTPPollThread::~RTPPollThread() ()

#7 0x0000000000507514 in jrtplib::RTPPollThread::~RTPPollThread() ()

#8 0x00000000004e051b in void jrtplib::RTPDelete<:rtppollthread>(jrtplib::RTPPollThread*, jrtplib::RTPMemoryManager*) ()

#9 0x00000000004db950 in jrtplib::RTPSession::BYEDestroy(jrtplib::RTPTime const&, void const*, unsigned long) ()

#10 0x00000000004213f1 in JtGb28181NvrAgent::HandleSdpReq_CloseVideo (this=0x1442060, CallID=...) at ../JtGb28181NvrAgent.cpp:4600

#11 0x0000000000416497 in JtGb28181NvrAgent::Thread (this=0x1442060) at ../JtGb28181NvrAgent.cpp:2669

#12 0x0000000000424675 in JtGb28181NvrAgent::StartWork (this=0x1442060, Config=0x0, RunMode=0) at ../JtGb28181NvrAgent.cpp:5333

#13 0x000000000040d22c in main (argc=1, argv=0x7fff33f8b738) at ../main.cpp:174

由上可知线程9171和10942线程卡住的地方,是再jrtplib里卡住了,函数如下

int RTPUDPv4Transmitter::AbortWait()

{

if (!init)

return ERR_RTP_UDPV4TRANS_NOTINIT;

MAINMUTEX_LOCK

if (!created)

{

MAINMUTEX_UNLOCK

return ERR_RTP_UDPV4TRANS_NOTCREATED;

}

if (!waitingfordata)

{

MAINMUTEX_UNLOCK

return ERR_RTP_UDPV4TRANS_NOTWAITING;

}

AbortWaitInternal();

MAINMUTEX_UNLOCK

return 0;

}

void RTPUDPv4Transmitter::AbortWaitInternal()

{

#if (defined(WIN32) || defined(_WIN32_WCE))

send(abortdesc[1],"*",1,0);

#else

if (write(abortdesc[1],"*",1))

{

// To get rid of __wur related compiler warnings

}

#endif // WIN32

}MAINMUTEX_LOCK是加锁,MAINMUTEX_UNLOCK是去锁,为什么会出现锁未去掉的情况呢,最后发现是在结束一个线程时使用了pthread_cancel函数,pthread_cancel可能在线程取消点就退出线程了,这里就是AbortWaitInternal函数的write调用处结束线程

,就导致MAINMUTEX_UNLOCK无法被调用,从而出现了死锁。

针对该问题做出代码上的修改,解决问题

通过这次bug,得出一个结论,除非你知晓代码及调用的每一个细节,否则不要轻易使用pthread_cancel来结束线程!!

自定义Usecase/Pipeline Summary of Custom Usecase and Pipeline Configuration in SA8650 QCX Framework This article elaborates on the complete process of customizing a new Usecase and Pipeline based on the SA8650 QCX framework to meet OEM and Tier1 customization requirements, with 阅读详情

相关推荐

jrtplib-3.9.1;jrtplib-3.7.1;jthread-1.3.1

jrtplib-3.9.1;jrtplib-3.7.1;jthread-1.3.1

在GLIBC里查找系统调用

有些系统调用在GLIBC里是找不到相应的函数的

小猪爱拱地 4212

T68型卧式镗床PLC控制系统设计.doc

T68型卧式镗床PLC控制系统设计.doc

嵌入式linux学习笔-- 解决 Broken pipe

Thread 1 "logServer" received signal SIGPIPE, Broken pipe. 0x00007ffff7bc5a9e in __libc_send (fd=5, buf=0x5555555b2918, len=17, flags=0) at ../sysdeps/unix/sysv/linux/send.c:28 28 ../sysdeps/unix/sysv/linux/send.c: No such file or directory. 开发中遇到了如

jeason的博客 1104

linux 读取IO出现阻塞

在您提供的代码片段中,您正在尝试打开一个设备文件(很可能是一个输入设备,如键盘或触摸屏)并使用 read 函数来读取该设备上的事件。但是,您提到 read 调用似乎一直阻塞。最后,请注意,直接操作设备文件通常需要深入的Linux内核和设备驱动程序知识。如果您不熟悉这些概念,请确保在尝试之前仔细研究相关文档和示例代码。

weixin_38849487的博客 638

linuxread阻塞原理,c - 为什么在这种情况下read()会阻塞?(Linux epoll) - 堆栈内存溢出...

我是unix programming新手,今天我正在尝试epoll但遇到了问题。在level-triggered模式下,我认为每个新输入事件(包括Ctrl-D都会导致epoll_wait返回。 工作正常。 但是,当我键入aaa ,请Ctrl-D ,然后read块。 当我键入Ctrl-D ,没有。你能解释一下会发生什么吗?当epoll_wait完成并根据fd准备好时,我应该读取所​​有数据吗?...

weixin_35997999的博客 908

linux select read阻塞_图解Linux的IO模型和相关技术

阻塞IO模型(Blocking I/O)Linux 内核一开始提供了 read 与 write 阻塞式操作。当客户端连接时,会在对应进程的文件描述符目录(/proc/进程号/fd)生成对应的文件描述符(0 标准输入;1 标准输出;2 标准错误输出;),比如 fd 8 , fd 9;应用程序需要读取的时候,通过系统调用 read (fd8)读取,如果数据还没到来,此应用程序的进程或线程会阻塞等待。m...

weixin_39801714的博客 950

Linux---线程---全面讲解

Linux线程作为轻量级执行单元,在系统编程中扮演着关键角色。本文系统讲解了线程基础概念、核心API、同步机制和高级特性。重点内容包括:线程与进程的本质区别,Linux通过轻量级进程实现线程;pthread库的核心操作如创建、等待、终止和分离线程;多种同步机制(互斥锁、条件变量、读写锁等)的原理与使用场景;线程局部存储、线程安全等高级特性;以及死锁、线程泄漏等常见问题的解决方案。文章结合代码示例和底层实现细节,帮助开发者深入理解Linux线程的运行机制和最佳实践。

我的博客主要是用来给我自己复习的,主要是上传一些知识点,小型的项目和功能模块,如果有什么问题或错误麻烦联系我! 1794

Linux多线程编程核心技术与实践指南

多线程编程是现代操作系统实现并发执行的核心技术,通过创建多个执行流共享进程资源来提高程序效率。POSIX线程(pthread)作为Linux标准线程接口,提供了线程创建、同步等基础API。线程同步机制如互斥锁(mutex)和条件变量(condition variable)解决了资源共享冲突问题,而读写锁(read-write lock)则优化了读多写少场景。在工程实践中,线程池技术能有效管理系统线程资源,原子操作确保数据竞争安全。这些技术广泛应用于高并发服务器、并行计算等场景,是提升系统性能的关键手段。通过

420

Linux线程】线程控制全解析:终止、join/detach、cancel、线程栈与 NPTL(下篇)

pthread_create 创建线程↓线程在共享地址空间中独立执行↓return / pthread_exit / cancel 结束当前线程↓joinable 由 pthread_join 等待并回收detached 在线程结束后自动回收线程资源↓glibc/NPTL 借助 clone 能力建立同线程组的内核调度实体线程入口 return 与只结束当前线程,exit()或 main 返回会终止整个进程;

weixin_64304261的博客 668

Linux系统】汇总

01_buildroot的配置方法_哔哩哔哩_bilibiliYocto嵌入式Linux大杀器-合集_哔哩哔哩_bilibili。

qq_58358642的博客 53

linux内核启动卡死在readl,linux内核学习之启动程序模块

linux引导程序解析bootsect程序,驻留在磁盘的第一个扇区中(0磁道 0磁头 1 扇区)。在BIOS加点检测之后,该引导程序会自动地加载在内存的0x7c00处。bootsect程序在运行时,会首先将自身移动到0x90000处开始执行,并将从第二个扇区开始的共4个扇区大小的setup程序移动到,紧紧挨着该程序的0x90200处。然后会使用BIOS中断int13 取当前引导盘的参数,接着在屏幕...

weixin_39597399的博客 803

linux系统函数read和write

一、read/write 函数 read函数从打开的设备或文件中读取数据。 #include ssize_t read(int fd, void *buf, size_t count); 返回值:成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0 参数count是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前

一璐有你的专栏 2154

linux文件操作函数read,!linux 文件操作 read函数为什么总是读不出数据,哪里出错了...

求救!linux 文件操作 read函数为什么总是读不出数据,哪里出错了本帖最后由 jj2060 于 2014-11-06 16:59:35 编辑下面这段代码没有报错,但是就是读不出文件中的数据,求高手指教,弄了好久,就是弄不出来#include#include#include#include#include#include#defineCREATE_MODE0755#de...

weixin_42471823的博客 1349

源码分析JRTPLIB之PollThread

读下PollThread源码和ThreadPool源码(https://github.com/progschj/ThreadPool)可以发现采用的线程间通信都是用的全局变量stop。这里提一下PollThread应该不是指的线程池,而是一种线程内部的管理机制。这两个都采用了同一种思想就是通过读取全局变量来控制线程的情况,当有函数修改了全局变量要求线程停止,其他处理函数读取到这个变量...

Parallel2333的博客 1388

关于linux下的死锁(程序卡住)的定位检测

定位方法:(1)如系统存在运行日志,首先分析日志信息。(2)利用pstack工具打印出此时系统的存在线程堆栈快照。(3)有些阻塞栈可能是因为它需要等待前面的线程执行结束才可以执行,所以要先确定依赖关系。(4)若问题可以复现,可以利用gdb调试系统,但若不确定问题是否可以复现,则推荐不要使用gdb, 因为会破坏问题产生的环境,gdb在一定程度上会影响系统运行导致卡住的因素由成立变成不成...

djm82755的博客 3792

JRtplib开发笔(三):JRtplib库编程使用说明

原博主博客地址:https://blog.csdn.net/qq21497936 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/84957120 《JRtplib开发笔(一):JRtplib简介、JThread库编译》:https://blog.csdn.net/qq21497936/article/details/8478...

长沙红胖子 Qt・西安|省级科研团队从业背景,深耕双一流体系高精尖技术配套研发|剥离高精尖机理,沉淀高端特种行业领域 Qt 工程化落地经验|博文仅分享通用技术总结,输出公开普适工程思路。 4万+

死锁编码及定位分析

死锁是指两个或者两个以上的进程在执行过程中,因争夺资源而造成的一种相互等待的现象,若无外力干涉将无法推进下去,如果系统资源充足,进程资源都能够满足,死锁出现的可能性就很低,否则就会因争夺资源而陷入死死锁 Linux ps -ef | grep XXX ls -l Windows 下java运行程序也有类似于ps 查看进行的命令但是目前我们需要查看的是 java jps = java ps jps -l 找到出现问题的进程号 8804...

NotRepent的博客 286

linux gdb运行不下去的程序调试方法

1、这些程序一般都是有while循环或者等待阻塞(例如服务器程序),这样的话,一般的可以让程序先运行起来,然后用gdb调试子程序;2、考虑另一种情况,如果在makeDaemon成功之后到while循环之前的代码出问题了,程序直接退出了,怎么调试?daemon程序一般都要停止父进程,重新设置会话,这样的程序gdb到这里就会结束,无法跟踪到下一步。B、gdb窗口输入n,回车,连续三次,自动运行到kill代码的下一行。其实也可以用gdb,但是先让程序停在makeDaemon成功之后。

xxpr_ybgg的博客 984

linuxgdb进程遇到的问题和坑

文章目录一、非生产环境中可以gdb到一个进程里面,但是有时候停顿太久,gdb附身到这个进程会挂掉,这时候就需要杀死这个gdb进程二、gdb调试程序的时候,有时gdb会因为某些原因crash掉。这时被调试的那个进程往往就成了僵尸进程。这种僵尸进程用killall是杀不掉的,用kill -9或者kill -SIGKILL也是杀不掉的,甚至退出用户登录也杀不掉。很多人这时候只好reboot机器。三、gdb的print打印默认打印不全四、让被gdb调试的程序能够接受信号五、函数明明存在,添加断点却无效六、断点的类型

谢白羽 4806
上一篇: android集合方法,java Android List深拷贝的两种方式
下一篇: linux dstat,dstat 用法详解
天日可人
博客等级 码龄6年 38粉丝 744原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值