信号处理函数误用不可重入函数导致的进程死锁情况
Posted jialin0x7c9
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了信号处理函数误用不可重入函数导致的进程死锁情况相关的知识,希望对你有一定的参考价值。
记一次进程死锁的情况:
某天突然发现进程不再运行处理且有没有崩溃产生core文件;
使用gdb -p pid查看堆栈信息如下:
1 #0 0x000000376faf83ae in __lll_lock_wait_private () from /lib64/libc.so.6 2 #1 0x000000376fa7d35b in _L_lock_10288 () from /lib64/libc.so.6 3 #2 0x000000376fa7ab83 in malloc () from /lib64/libc.so.6 4 #3 0x000000376fa80f42 in strdup () from /lib64/libc.so.6 5 #4 0x000000376fa9d9c1 in tzset_internal () from /lib64/libc.so.6 6 #5 0x000000376fa9db39 in __tz_convert () from /lib64/libc.so.6 7 #6 0x000000376fa9bc59 in ctime () from /lib64/libc.so.6 8 #7 0x0000000000405017 in AdAnalizeBayu::sigHandle (sig=14) at AdAnalizeBayu.cpp:56 9 #8 <signal handler called> 10 #9 0x000000376fa79ade in _int_malloc () from /lib64/libc.so.6 11 #10 0x000000376fa7a7ed in calloc () from /lib64/libc.so.6 12 #11 0x000000000042aaeb in operator new (size=48) at memcheck.cpp:302 13 #12 0x000000000041c3cf in __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, std::string> > >::allocate ( 14 this=0x7ffca027e950, __n=1) at /usr/include/c++/4.8.2/ext/new_allocator.h:104 15 #13 0x000000000041c2b8 in std::_Rb_tree<std::string, std::pair<std::string const, std::string>, std::_Select1st<std::pair<std::string const, std::string> >, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > >::_M_get_node (this=0x7ffca027e950) 16 at /usr/include/c++/4.8.2/bits/stl_tree.h:370 17 #14 0x000000000041c1bf in std::_Rb_tree<std::string, std::pair<std::string const, std::string>, std::_Select1st<std::pair<std::string const, std::string> >, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > >::_M_create_node (this=0x7ffca027e950, 18 __x=...) at /usr/include/c++/4.8.2/bits/stl_tree.h:380 19 #15 0x000000000041beb4 in std::_Rb_tree<std::string, std::pair<std::string const, std::string>, std::_Select1st<std::pair<std::string const, std::string> >, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > >::_M_insert_ (this=0x7ffca027e950, 20 __x=0x0, __p=0x27bfa00, __v=...) at /usr/include/c++/4.8.2/bits/stl_tree.h:1023 21 #16 0x000000000041b8b0 in std::_Rb_tree<std::string, std::pair<std::string const, std::string>, std::_Select1st<std::pair<std::string const, std::string> >, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > >::_M_insert_unique_ ( 22 this=0x7ffca027e950, __position=..., __v=...) at /usr/include/c++/4.8.2/bits/stl_tree.h:1482 23 #17 0x000000000041b6a2 in std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > >::insert (this=0x7ffca027e950, __position=..., __x=...) at /usr/include/c++/4.8.2/bits/stl_map.h:648 24 #18 0x000000000041b48f in std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > >::operator[] (this=0x7ffca027e950, __k=...) at /usr/include/c++/4.8.2/bits/stl_map.h:469 25 #19 0x0000000000441ada in kfc::CCgiPara::Decode () at kfc_parsepara.cpp:147 26 #20 0x000000000042248b in CUdpServer::OnDoProcess () at udp_server.cpp:76 27 #21 0x00000000004240d5 in CUServer::ReadFromSvrPort (this=0x6622a0 <CUdpServer::getInstance()::srv>) at userver.cpp:97 28 #22 0x000000000042427f in CUServer::Run (this=0x6622a0 <CUdpServer::getInstance()::srv>) at userver.cpp:121 29 #23 0x000000000041aaf6 in main (argc=2, argv=0x7ffca027ff78) at main.cpp:62
由堆栈编号11可以看到程序在往std容器map内插入一个红黑树节点调用了系统调用_int_malloc()函数申请一片空间的时候,定时器信号过来,进程进入了信号处理函数(堆栈编号8)。
此时这片内存空间是有被加上锁的;
在信号处理函数内调用了库函数ctime(),这个函数后来查阅资料得知是不可重入函数(即会导致结果不可预知)。在该函数内调用了malloc函数会对同一批空间加锁,由于这篇内存空间已被之前加过锁导致进程在此处阻塞。进程在信号处理函数内阻塞等待std容器添加完后释放锁,std容器添加过程又在等待信号处理函数处理完毕后释放锁。导致进程进入死锁状态。
解决办法:
ctime函数在我的信号处理函数内不是必须存在的,因此做了删减另外实现。死锁情况解决。
总结:
在信号处理函数内一定不要使用不可重入函数。虽然posix标准规定标准库函数必须都是可重入函数,但仍有少数是不可重入函数:
以上是关于信号处理函数误用不可重入函数导致的进程死锁情况的主要内容,如果未能解决你的问题,请参考以下文章