• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            那誰(shuí)的技術(shù)博客

            感興趣領(lǐng)域:高性能服務(wù)器編程,存儲(chǔ),算法,Linux內(nèi)核
            隨筆 - 210, 文章 - 0, 評(píng)論 - 1183, 引用 - 0
            數(shù)據(jù)加載中……

            服務(wù)器定時(shí)器處理要注意的問題

            今天早上,例行巡查服務(wù)器,我用strace命令跟蹤服務(wù)器進(jìn)程的時(shí)候, 發(fā)現(xiàn)有幾個(gè)服務(wù)器進(jìn)程出現(xiàn)了死鎖情況, gdb繼續(xù)跟進(jìn),顯示如下:

            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<std::_List_node<TTimeEvent> >::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<TTimeEvent> >::_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 <signal handler called>
            #
            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_traits<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
            在#13處,調(diào)用free函數(shù), 然后進(jìn)入與之相關(guān)的libc函數(shù)調(diào)用中.但是, 在這個(gè)調(diào)用還沒有完結(jié)之前被定時(shí)器管理模塊中斷, 進(jìn)入了定時(shí)器處理的部分, 在在這個(gè)處理中同樣調(diào)用了free函數(shù), 于是出現(xiàn)了死鎖的情況--因?yàn)閙alloc/free函數(shù)族不是可重入的, 在這里有一篇相關(guān)的文章.

            我曾經(jīng)想在我的服務(wù)器代碼中盡量減少對(duì)象的構(gòu)造/析構(gòu), 但是想了一下, 這個(gè)策略不是治本的辦法, 這意味著我必須在寫代碼的時(shí)候處處小心, 今天可能在A處出現(xiàn)死鎖, 明天可能會(huì)在B處出現(xiàn).而且, 由于使用的是C++, 一些局部對(duì)象的構(gòu)造和析構(gòu)是不可避免的.

            于是, 解決這個(gè)問題的思路就改變?yōu)?盡量的簡(jiǎn)單化定時(shí)器處理操作.目前我想到的一個(gè)策略時(shí), 一個(gè)定時(shí)器被觸發(fā)的時(shí)候, 置一個(gè)標(biāo)志位, 而不是在在觸發(fā)的時(shí)候調(diào)用相應(yīng)的處理函數(shù), 然后在服務(wù)器的主循環(huán)中判斷是否被置位, 如果是的話再去調(diào)用相關(guān)的處理函數(shù).

            于是, 原來(lái)的思路就是:
            // 該函數(shù)在定時(shí)器到時(shí)的時(shí)候被觸發(fā)
            void signal()
            {
               
            // 定時(shí)器處理函數(shù)
               dosomething();
            }

            while(1)
            {
               服務(wù)器主循環(huán);
            }

            修改之后的思路是:
            int violate g_alarm = 0;

            // 該函數(shù)在定時(shí)器到時(shí)的時(shí)候被觸發(fā)
            void signal()
            {
              g_alarm 
            = 1;
            }

            while(1)
            {
               服務(wù)器主循環(huán);
               
            if (g_alarm)
               {
                   
            // 定時(shí)器處理函數(shù)
                  dosomething();
                  g_alarm 
            = 0;
               }
            }


            這是大概的模型上面的改變.這是我目前能想到的處理該問題的最好辦法, 如果哪位有更好的辦法歡迎補(bǔ)充.


            posted on 2008-10-16 19:08 那誰(shuí) 閱讀(5084) 評(píng)論(10)  編輯 收藏 引用 所屬分類: 服務(wù)器設(shè)計(jì)Linux/Unix

            評(píng)論

            # re: 服務(wù)器定時(shí)器處理要注意的問題  回復(fù)  更多評(píng)論   

            認(rèn)同你的做法
            這種做法很常見,簡(jiǎn)單實(shí)用
            2008-10-16 21:49 | LOGOS

            # re: 服務(wù)器定時(shí)器處理要注意的問題  回復(fù)  更多評(píng)論   

            內(nèi)存池
            2008-10-17 12:46 | kevin

            # re: 服務(wù)器定時(shí)器處理要注意的問題  回復(fù)  更多評(píng)論   

            我覺得定時(shí)器只負(fù)責(zé)產(chǎn)生消息即可。
            2008-10-17 13:23 | lihui

            # re: 服務(wù)器定時(shí)器處理要注意的問題  回復(fù)  更多評(píng)論   

            是不是要加鎖?小弟不才,請(qǐng)指教.
            while & signal 都修改了這個(gè)violate,所以考慮要不要加鎖?
            2008-10-20 08:39 | ocean

            # re: 服務(wù)器定時(shí)器處理要注意的問題  回復(fù)  更多評(píng)論   

            明白了,不加鎖,呵呵,讀你的東西真是受用.
            2008-10-20 08:42 | ocean

            # re: 服務(wù)器定時(shí)器處理要注意的問題  回復(fù)  更多評(píng)論   

            這樣的做法 很簡(jiǎn)單,但是很難看。

            效率高一些,卻不優(yōu)雅。 擴(kuò)展比較難。

            如果多一些事件的話,可能把主線程搞成非常亂
            2009-04-24 17:26 | 妞妞

            # re: 服務(wù)器定時(shí)器處理要注意的問題[未登錄]  回復(fù)  更多評(píng)論   

            @妞妞
            那有什么好的建議沒有呢?
            2009-04-27 17:07 | 那誰(shuí)

            # re: 服務(wù)器定時(shí)器處理要注意的問題  回復(fù)  更多評(píng)論   

            建議看看libevent的定時(shí)器實(shí)現(xiàn)。
            很優(yōu)美的實(shí)現(xiàn)。將IO,信號(hào)和定時(shí)器都作為事件來(lái)統(tǒng)一進(jìn)行分發(fā)。
            2009-12-26 05:35 | 浩毛

            # re: 服務(wù)器定時(shí)器處理要注意的問題  回復(fù)  更多評(píng)論   

            假設(shè)現(xiàn)在g_alarm = 1,進(jìn)入了if中正在處理do_something,恰好現(xiàn)在產(chǎn)生一個(gè)信號(hào)使 g_alarm = 1,當(dāng)do_something退出時(shí), g_alarm = 0了,所以丟失了一個(gè)信號(hào)事件。這個(gè)問題該怎么辦?
            2011-01-15 10:18 | xunuj

            # re: 服務(wù)器定時(shí)器處理要注意的問題  回復(fù)  更多評(píng)論   

            剛從博主《libevent 事件處理框架分析》中看到
            “信號(hào)事件:所有的信號(hào)都注冊(cè)回調(diào)函數(shù)為evsignal_handler(在signal.c中),這個(gè)函數(shù)的功能就是在某信號(hào)被觸發(fā)的時(shí)候?qū)⒃撔盘?hào)被觸發(fā)的計(jì)數(shù)器加1,同時(shí)置一個(gè)標(biāo)志位表示有信號(hào)被觸發(fā).“
            2011-01-15 10:34 | xunuj
            久久婷婷色香五月综合激情| 久久亚洲电影| 99国产欧美久久久精品蜜芽| 国产精品毛片久久久久久久| www亚洲欲色成人久久精品| 午夜福利91久久福利| 久久香蕉国产线看观看精品yw| 青青草原综合久久| 精品综合久久久久久98| 久久久国产精品福利免费| 久久亚洲精品成人无码网站| 久久人人爽人人爽人人片av高请 | 国产成人久久精品一区二区三区| 久久精品国产精品亚洲精品 | 亚洲国产另类久久久精品| 99久久国产综合精品成人影院 | 99久久精品这里只有精品| 亚洲Av无码国产情品久久| 久久久久国产一级毛片高清版| 国产精品久久久久a影院| 丁香久久婷婷国产午夜视频| 亚洲午夜久久久久久久久电影网| 久久国产视频网| 久久久精品午夜免费不卡| 久久综合亚洲欧美成人| 青青草原综合久久大伊人| 久久毛片免费看一区二区三区| 精品999久久久久久中文字幕| 一本久久知道综合久久| 久久精品日日躁夜夜躁欧美| 久久国产三级无码一区二区| 成人a毛片久久免费播放| 9久久9久久精品| 久久精品国内一区二区三区| 国产精品久久久久影视不卡| 久久天天躁狠狠躁夜夜网站| 日韩久久久久久中文人妻 | 久久精品国产清自在天天线| 久久91精品国产91久| 久久久精品人妻一区二区三区蜜桃| 国产精品久久久久久五月尺|