疑难杂症之malloc死锁__lll_lock_wait_private

2023-10-12 22:40

本文主要是介绍疑难杂症之malloc死锁__lll_lock_wait_private,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

查看glibc源码可知, malloc内部是有锁的。那说明malloc是一个线程安全型函数,但是它不是一个可重入函数。重入的意思是,比如当前线程正在做malloc, 如果此时因为某种原因触发了信号,那么操作系统会保存好现场(正在执行的malloc),转而去执行信号处理函数,如果信号处理函数里面又有malloc的调用,那么此时就发生了malloc重入。当malloc重入时,可能导致线程死锁。

main.c 如下:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>
using namespace std;
void signal_handler(int signum);#define NUM 100000void* test( void* args )
{    while(1)    {        printf("try to malloc in test, thread id = %u\r\n", pthread_self());        void *p = malloc(NUM);       }    return NULL;
}int main()
{         signal(SIGTERM, signal_handler); pthread_t thread1;    pthread_create(&thread1, NULL, test, NULL);for(;;){printf("malloc in main function, thread id = %u\r\n", pthread_self());void *p = malloc(NUM);}pthread_join(thread1, NULL);return 0;
}   void signal_handler(int signum)
{   printf("receive SIGTERM, malloc again, thread id = %u\r\n", pthread_self());void *p = malloc(NUM);
}

主线程和子线程都一直在做malloc, 信号处理函数也在调用malloc. 此时运行一个脚本,让其不断触发SIGTERM,那么程序运行一段时间之后可能发生死锁。

编译:

g++ main.c -lpthread

运行:

./a.out

查看线程号:

ps  -ef | grep a.out

root       6378   5558  0 11:21 pts/1    00:00:01 ./a.out

同时启动一个javascript, 让其不断触发SIGTERM,脚本如下:

# $language = "JScript"
# $interface = "1.0"function main()
{shellCmds();
}function shellCmds()
{for(;;){var cmd1 = "kill 6378";crt.Screen.Send(cmd1+"\r\n");}}

运行一段时间之后系统死锁了:

 查看此时的调用栈:

#0  0x00007f2258ed597e in __lll_lock_wait_private () from /lib64/libc.so.6
#1  0x00007f2258e6fc93 in _L_lock_9971 () from /lib64/libc.so.6
#2  0x00007f2258e6e169 in malloc () from /lib64/libc.so.6     //第二次进入malloc
#3  0x0000000000400840 in signal_handler(int) ()
#4  <signal handler called>
#5  0x00007f2258ec541a in mmap64 () from /lib64/libc.so.6
#6  0x00007f2258e6cbc4 in _int_malloc () from /lib64/libc.so.6
#7  0x00007f2258e6e174 in malloc () from /lib64/libc.so.6       //第一次进入malloc
#8  0x000000000040080e in main ()

然而有时候,malloc的调用可能是间接的,比如往文件里面写log也会调用malloc, 以下是一段写文件的调用栈,最终block在malloc

#0  __lll_lock_wait_private (futex=0x74800018) at ./lowlevellock.c:32
#1  0x76120b08 in __GI___libc_malloc (bytes=bytes@entry=4096) at malloc.c:3063
#2  0x7610548c in __GI__IO_file_doallocate (fp=0x74a43428) at filedoalloc.c:101
#3  0x76118adc in __GI__IO_doallocbuf (fp=fp@entry=0x74a43428) at genops.c:365
#4  0x76115b60 in _IO_new_file_seekoff (fp=0x74a43428, offset=0, dir=1, mode=<optimized out>) at fileops.c:960
#5  0x76117360 in _IO_new_file_attach (fp=fp@entry=0x74a43428, fd=fd@entry=218) at fileops.c:379
#6  0x76111ecc in _IO_vdprintf (d=d@entry=218, format=format@entry=0x765aa1d8 "%u", arg=arg@entry=0x74a43520) at iovdprintf.c:46
#7  0x760f1874 in __GI___dprintf (d=d@entry=218, format=format@entry=0x765aa1d8 "%u") at dprintf.c:33

最后总结:

1 malloc是不可重入函数, 如果重入了可能会死锁。所以信号处理函数里面不能调用malloc.

2 malloc的调用有可能是间接地或者说是隐式的。所以信号处理函数应该尽可能简单, 比如只设置一个flag, 然后让其他线程根据这个flag来做其它事情。

这篇关于疑难杂症之malloc死锁__lll_lock_wait_private的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/198947

相关文章

SQL Server数据库死锁处理超详细攻略

《SQLServer数据库死锁处理超详细攻略》SQLServer作为主流数据库管理系统,在高并发场景下可能面临死锁问题,影响系统性能和稳定性,这篇文章主要给大家介绍了关于SQLServer数据库死... 目录一、引言二、查询 Sqlserver 中造成死锁的 SPID三、用内置函数查询执行信息1. sp_w

Java死锁问题解决方案及示例详解

《Java死锁问题解决方案及示例详解》死锁是指两个或多个线程因争夺资源而相互等待,导致所有线程都无法继续执行的一种状态,本文给大家详细介绍了Java死锁问题解决方案详解及实践样例,需要的朋友可以参考下... 目录1、简述死锁的四个必要条件:2、死锁示例代码3、如何检测死锁?3.1 使用 jstack3.2

解决mysql插入数据锁等待超时报错:Lock wait timeout exceeded;try restarting transaction

《解决mysql插入数据锁等待超时报错:Lockwaittimeoutexceeded;tryrestartingtransaction》:本文主要介绍解决mysql插入数据锁等待超时报... 目录报错信息解决办法1、数据库中执行如下sql2、再到 INNODB_TRX 事务表中查看总结报错信息Lock

Mysql如何解决死锁问题

《Mysql如何解决死锁问题》:本文主要介绍Mysql如何解决死锁问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录【一】mysql中锁分类和加锁情况【1】按锁的粒度分类全局锁表级锁行级锁【2】按锁的模式分类【二】加锁方式的影响因素【三】Mysql的死锁情况【1

MySQL的隐式锁(Implicit Lock)原理实现

《MySQL的隐式锁(ImplicitLock)原理实现》MySQL的InnoDB存储引擎中隐式锁是一种自动管理的锁,用于保证事务在行级别操作时的数据一致性和安全性,本文主要介绍了MySQL的隐式锁... 目录1. 背景:什么是隐式锁?2. 隐式锁的工作原理3. 隐式锁的类型4. 隐式锁的实现与源代码分析4

MySQL中Next-Key Lock底层原理实现

《MySQL中Next-KeyLock底层原理实现》Next-KeyLock是MySQLInnoDB存储引擎中的一种锁机制,结合记录锁和间隙锁,用于高效并发控制并避免幻读,本文主要介绍了MySQL中... 目录一、Next-Key Lock 的定义与作用二、底层原理三、源代码解析四、总结Next-Key L

MySql死锁怎么排查的方法实现

《MySql死锁怎么排查的方法实现》本文主要介绍了MySql死锁怎么排查的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录前言一、死锁排查方法1. 查看死锁日志方法 1:启用死锁日志输出方法 2:检查 mysql 错误

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

MYSQL事务死锁问题排查及解决方案

《MYSQL事务死锁问题排查及解决方案》:本文主要介绍Java服务报错日志的情况,并通过一系列排查和优化措施,最终发现并解决了服务假死的问题,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录问题现象推测 1 - 客户端无错误重试配置推测 2 - 客户端超时时间过短推测 3 - mysql 版本问

Java访问修饰符public、private、protected及默认访问权限详解

《Java访问修饰符public、private、protected及默认访问权限详解》:本文主要介绍Java访问修饰符public、private、protected及默认访问权限的相关资料,每... 目录前言1. public 访问修饰符特点:示例:适用场景:2. private 访问修饰符特点:示例: