• <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>

            那誰的技術(shù)博客

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

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

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

            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ù), 然后進入與之相關(guān)的libc函數(shù)調(diào)用中.但是, 在這個調(diào)用還沒有完結(jié)之前被定時器管理模塊中斷, 進入了定時器處理的部分, 在在這個處理中同樣調(diào)用了free函數(shù), 于是出現(xiàn)了死鎖的情況--因為malloc/free函數(shù)族不是可重入的, 在這里有一篇相關(guān)的文章.

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

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

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

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

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

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

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


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


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

            評論

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

            認同你的做法
            這種做法很常見,簡單實用
            2008-10-16 21:49 | LOGOS

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

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

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

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

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

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

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

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

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

            這樣的做法 很簡單,但是很難看。

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

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

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

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

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

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

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

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

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

            剛從博主《libevent 事件處理框架分析》中看到
            “信號事件:所有的信號都注冊回調(diào)函數(shù)為evsignal_handler(在signal.c中),這個函數(shù)的功能就是在某信號被觸發(fā)的時候?qū)⒃撔盘柋挥|發(fā)的計數(shù)器加1,同時置一個標志位表示有信號被觸發(fā).“
            2011-01-15 10:34 | xunuj
            久久久久亚洲爆乳少妇无| 久久精品国产亚洲5555| 色欲综合久久躁天天躁| 91亚洲国产成人久久精品| 日本强好片久久久久久AAA| 伊人久久大香线蕉综合网站| 久久av免费天堂小草播放| 曰曰摸天天摸人人看久久久| 狠狠色丁香久久综合五月| 亚洲AV日韩AV天堂久久| 久久久精品人妻一区二区三区四 | 精品免费tv久久久久久久| 香蕉久久夜色精品升级完成| 色8久久人人97超碰香蕉987| 人妻精品久久久久中文字幕69 | 无码任你躁久久久久久老妇| 欧洲国产伦久久久久久久| 亚洲午夜精品久久久久久app| 亚洲欧美国产精品专区久久| 伊人久久大香线蕉AV一区二区| 久久午夜夜伦鲁鲁片免费无码影视| 久久成人国产精品免费软件| 亚洲va国产va天堂va久久| 国产精品久久免费| 国产精品无码久久久久| 久久亚洲国产最新网站| 亚洲AV日韩精品久久久久| 国产精品伦理久久久久久| 久久亚洲精品无码VA大香大香| 青草国产精品久久久久久| 日本久久久久久中文字幕| 亚洲国产天堂久久综合| 久久精品国产亚洲AV电影| 精品久久久久久无码国产| 亚洲精品无码久久久影院相关影片 | 久久精品成人免费国产片小草| 99久久这里只精品国产免费| 久久久亚洲欧洲日产国码二区 | 少妇人妻综合久久中文字幕| 久久精品国产久精国产| 久久亚洲AV无码精品色午夜|