Linux server timer processing to pay attention to the problem

  

This morning, routine inspection server, I used the strace command to track the server process, found that several server processes have a deadlock situation, gdb continues to follow up, as shown below :
gdb) bt # 0 0x00ff9410 in __kernel_vsyscall () # 1 0x004d593e in __lll_mutex_lock_wait () from /lib/libc.so.6#2 0x00465b38 in _L_lock_14080 () from /lib/libc.so.6#3 0x00464df4 in free () from /lib/libc.so.6#4 0x006c7691 in operator delete () from /usr/lib/libstdc++.so.6#5 0x08059cfb in __gnu_cxx :: new_allocator & lt; std :: _ List_node & lt; TTimeEvent & gt; & gt ;: :deallocate (this=0x98e0064, __p=0x98e1218)at /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/ext /new_allocator.h:94#6 0x08059d20 in std::_List_base<TTimeEvent, std::allocator<TTimeEvent> >::_M_put_node (this=0x98e0064, __p=0x98e1218)at /usr/lib/gcc/i386-redhat- Linux/4.1.1/../../../../include/c++/4.1.1/bits/stl_list.h:320#7 0x08059d81 in std::list<TTimeEvent, std::allocator<TTimeEven t> >::_M_erase (this=0x98e0064, __position={_M_node = 0x98e1218}) at /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../Include/c++/4.1.1/bits/stl_list.h:1150#8 0x08059db3 in std::list<TTimeEvent, std::allocator<TTimeEvent> >::pop_front (this=0x98e0064)at /usr/lib/gcc /i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/bits/stl_list.h:747#9 0x08059334 in CTimerManager::Process (this=0x98e0058 ) at src /timermanager.cpp: 168 # 10 0x080597dd in Process (nSigNo = 14) at src /timermanager.cpp: 199 # 11 & lt; signal handler called & gt; # 12 0x004612ba in _int_free () from /lib/libc.so. 6 # 13 0x00464e00 in free () from /lib/libc.so.6#14 0x006c7691 in operator delete () from /usr/lib/libstdc++.so.6#15 0x006a424d in std :: string :: _ Rep :: _ M_destroy () from /usr/lib/libstdc++.so.6#16 0x0069e40f in std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf ()from /usr /lib/libstdc++.so.6#17 0x0069fd7f in std::basic_stringstream<char, std::char_tr Aits<char>, std::allocator<char> >::~basic_stringstream ()from /usr/lib/libstdc++.so.6#18 0x080524ea in CDBMoudle::Insert (this=0x98e6e80, tFixkey=@0xbfe1c6ec) at src /dbmoudle.cpp: 59 # 19 0x08051718 in CConnectionTask :: ProcFixContent (this = 0x98e6510) at src /connectiontask.cpp: 218 # 20 0x0805196e in CConnectionTask :: HandleRead (this = 0x98e6510) at src /connectiontask.cpp: 86 # 21 0x08051a0f in CConnectionTask :: Handle (this = 0x98e6510, nEvent = 1) at src /connectiontask.cpp: 52 # 22 0x080585af in iServer :: Run (this = 0xbfe1c7e0) at src /server.cpp: 133 # 23 0x08055328 in main (argc=2, argv=0xbfe1c8b4) at src/main.cpp:19

At #13, call the free function, and then enter the libc function call associated with it. However, before this call is finished, The timer management module is interrupted and enters the part of the timer processing. In this process, the free function is also called, and the deadlock occurs. Because the malloc/free function family is not reentrant, there is an article here. Related articles. I used to want to be on my server generation Try to minimize the construction/destruction of the object in the code, but after thinking about it, this strategy is not a cure, which means that I have to be careful when writing the code. Today, there may be a deadlock at A, and tomorrow may be at B. It appears. Moreover, because of the use of C++, the construction and destruction of some local objects is inevitable. Therefore, the solution to this problem is changed to: try to simplify the timer processing operation as much as possible. When a timer is triggered, a flag is set instead of calling the corresponding handler at the time of the trigger, and then it is judged whether it is set in the main loop of the server, and if so, the relevant processing is called. Function. So, the original idea is:
//This function is triggered when the timer expires void signal(){//timer handler dosomething();}while(1){server main loop; }

The idea behind the change is:
int violate g_alarm = 0;//This function is triggered when the timer expires void signal(){g_alarm = 1;}while(1){server main loop ;if (g_alarm){//timer processing The number dosomething();g_alarm = 0;}}

This is the approximate change in the model. This is the best way I can think of dealing with this problem, if there is a better way to welcome it. Br>

Copyright © Windows knowledge All Rights Reserved