找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 20193|回复: 26

一个ACE中getq()时候产生的问题

[复制链接]
发表于 2009-11-25 10:15:39 | 显示全部楼层 |阅读模式
在我的网络程序中,getq()会在数据传输量很大的时候出现segmentation fault,Call Stack如下
#0  0x001d7526 in ACE_Message_Block::total_size_and_length (this=0xb7fc93a8, mb_size=@0xb5ac5f8c, mb_length=@0xb5ac5f88) at Message_Block.cpp:267
#1  0x080507a9 in ACE_Message_Queue <ACE_MT_SYNCH>::dequeue_head_i (this=0x9794dd0, first_item=@0xb5ac6040) at ../../../../usr/local/ACE_wrappers/ace/Message_Queue_T.cpp:1334
#2  0x08053e74 in ACE_Message_Queue <ACE_MT_SYNCH>::dequeue_head (this=0x9794dd0, first_item=@0xb5ac6040, timeout=0xb5ac6038)
    at ../../../../usr/local/ACE_wrappers/ace/Message_Queue_T.cpp:1786
#3  0x08057d4a in ACE_Task <ACE_MT_SYNCH>::getq (this=0x9794d50, mb=@0xb5ac6040, tv=0xb5ac6038) at ../../../../usr/local/ACE_wrappers/ace/Task_T.inl:24
#4  0x08056e6c in GateWayService::handle_output (this=0x9794d50, hdl=17) at /home/bigboss/codeblocks_workspace/gateway_server/src/client_connection.cpp:207
#5  0x001a807d in ACE_Select_Reactor_T <ACE_Reactor_Token_T <ACE_Token> >::notify_handle (this=0x9787938, handle=17, mask=2, ready_mask=@0x9787ecc, event_handler=0x9794d50,
    ptmf= <error reading variable>) at /usr/local/ACE_wrappers/ace/Select_Reactor_T.cpp:817
#6  0x001a738d in ACE_Select_Reactor_T <ACE_Reactor_Token_T <ACE_Token> >::dispatch_io_set (this=0x9787938, number_of_active_handles=4, number_of_handlers_dispatched=@0xb5ac6178,
    mask=2, dispatch_mask=@0x97879e0, ready_mask=@0x9787ecc, callback= <error reading variable>) at /usr/local/ACE_wrappers/ace/Select_Reactor_T.cpp:1205
#7  0x001a1409 in ACE_Select_Reactor_T <ACE_Reactor_Token_T <ACE_Token> >::dispatch_io_handlers (this=0x9787938, dispatch_set=@0x9787954, number_of_active_handles=@0xb5ac6194,
    number_of_handlers_dispatched=@0xb5ac6178) at /usr/local/ACE_wrappers/ace/Select_Reactor_T.cpp:1239
#8  0x001a19a2 in ACE_Select_Reactor_T <ACE_Reactor_Token_T <ACE_Token> >::dispatch (this=0x9787938, active_handle_count=4, dispatch_set=@0x9787954)
    at /usr/local/ACE_wrappers/ace/Select_Reactor_T.cpp:1367
#9  0x001a6ac3 in ACE_Select_Reactor_T <ACE_Reactor_Token_T <ACE_Token> >::handle_events (this=0x9787938, max_wait_time=0x0) at /usr/local/ACE_wrappers/ace/Select_Reactor_T.cpp:1447
#10 0x001fdc83 in ACE_Reactor::handle_events (this=0x9783738, max_wait_time=0x0) at Reactor.cpp:420
#11 0x0804ba0f in updateServer4Logic (argv=0x0) at /home/bigboss/codeblocks_workspace/gateway_server/main.cpp:88
#12 0x001e3b67 in ACE_OS_Thread_Adapter::invoke (this=0x9783800) at OS_Thread_Adapter.cpp:90
#13 0x001a95d1 in ace_thread_adapter (args=0x9783800) at Base_Thread_Adapter.cpp:116
#14 0x00c9850b in start_thread () from /lib/libpthread.so.0
#15 0x00bd9b2e in clone () from /lib/libc.so.6

出错是在
0x001d7526 in ACE_Message_Block::total_size_and_length (this=0xb7fc93a8, mb_size=@0xb5ac5f8c, mb_length=@0xb5ac5f88) at Message_Block.cpp:267
267          mb_size += i->size ();

这句,我怀疑可能是msg_queue_线程不安全,所以我将
class GateWayService : public ACE_Svc_Handler < ACE_SOCK_STREAM, ACE_NULL_SYNCH >
改为了
class GateWayService : public ACE_Svc_Handler < ACE_SOCK_STREAM, ACE_MT_SYNCH >
可是程序依旧出错,哪位前辈能指点下问题还可能出在哪儿吗?如果需要更多信息,请说明
发表于 2009-11-25 12:40:25 | 显示全部楼层

对getq的认识

getq只是dequeue_head_i的一个包装,对ACE_Message_Queue 来说是安全的,不会有任何问题,而且,ACE_Message_Queue 是非常健壮的,它唯一的缺陷就是有微乎其微的内部锁开销,其它没有任何问题。我想你的错误应该不在这里,而且堆栈跟踪也不是非常准确的,只能说在附近,尤其是多线程程序更是如此。

从你打出来的信息暂时看不出错误所在。是不是其它线程已经将队列删除了。多线程编程经常会出这种错。 呵呵。
 楼主| 发表于 2009-11-25 13:23:02 | 显示全部楼层
其实整个程序只有在这里会对msg_queue_进行操作,没有其他地方对其操作,想不通为什么.定位不准确的确我也考虑过,但是这个bug是几乎可以100%重现的,每次的call stack都是这样.所以我比较相信了就~
 楼主| 发表于 2009-11-25 15:48:33 | 显示全部楼层
这里贴出出问题处的函数:
int GateWayService::handle_output( ACE_HANDLE hdl )
{
    while( msg_queue_->is_empty()==0 ) {
        ACE_Message_Block* mb;
        ACE_Time_Value nowait( ACE_OS::gettimeofday() );
        ACE_SEH_TRY {

            getq( mb, &nowait );
        }
        ACE_SEH_EXCEPT ( EXCEPTION_EXECUTE_HANDLER){

            continue;
        }


        ACE_UINT32 left = send_dp_->capacity() - send_dp_->length();
        if( mb->length() > left ) {
            ACE_UINT8* buf;
            ACE_UINT32 bufSz = send_dp_->p_pack( buf );

            ACE_DEBUG ( ( LM_DEBUG, ACE_TEXT ( "line[%d] %s SEND Data to Client: bufSz = %d\n" ),
                                                                            __LINE__, __FUNCTION__, bufSz ) );

            ssize_t send_cnt = this->peer().send( buf, bufSz );
             if( send_cnt == -1 ) {
                 ACE_ERROR((LM_ERROR,ACE_TEXT("(%P|%t)%p\n"),ACE_TEXT("send")));
                 return -1;
             }
             send_dp_->release();
             send_dp_ = DataPackage::create( 1 );
        }
        send_dp_->append( ( ACE_UINT8* )mb->rd_ptr(), mb->length() );
        ACE_ERROR((LM_ERROR,ACE_TEXT("mb->rd_ptr()=%d mb->length()=%d\n"),*( ACE_UINT8* )mb->rd_ptr(),mb->length()));
        mb->release();
     }
    return 0;
}
发表于 2009-11-25 15:55:59 | 显示全部楼层
多线程的调试是很痛苦的。
我也正在调一个多线程的程序,问题很难重现,如果能找到必然重现的办法差不多也就找到原因了。痛苦啊。
 楼主| 发表于 2009-11-25 16:46:36 | 显示全部楼层
我这个程序实际上是单线程的=.=回头来看了看,其实只是对象不同,线程只有一个....那那个bug就更让人费解了
发表于 2009-11-25 17:21:22 | 显示全部楼层
首先,楼主使用ACE_MT_SYNCH初始化ACE_Svc_Handler是有必要的。
ACE_Svc_Handler的第二个模版参数会直接影响到ACE_Message_Queue的初始化使用的模版参数,
如果是用ACE_NULL_SYNCH初始化,那么ACE_Message_Queue就不是线程安全的。
其次,通过楼主的贴出来的代码,也没看出来什么问题,再多贴些代码出来吧。
 楼主| 发表于 2009-11-25 23:42:05 | 显示全部楼层
这里想问个问题,handle_output()和handle_timeout()是同一个线程还是不同的线程呢?
发表于 2009-11-26 09:18:48 | 显示全部楼层
看你Reactor使用的什么实现,
如果使用Select_Reactor是单线程的运行的,不需要线程保护机制。
如果使用线程池运行Reactor,比如TP_Reactor
同一对象的handle_output与handle_timeout会同时在不同的线程里被调用。
发表于 2009-11-26 14:18:32 | 显示全部楼层
void
ACE_Message_Block::total_size_and_length (size_t &mb_size,
                                          size_t &mb_length) const
{
  ACE_TRACE ("ACE_Message_Block::total_size_and_length");

  for (const ACE_Message_Block *i = this;
       i != 0;
       i = i->cont ())
    {
      mb_size += i->size ();
      mb_length += i->length ();
    }
}

无法继续跟进到size ()里去了么?如果这样那就是i的问题了。i不是0,但又不是指向一个有效的message block。能确保最初拼接复合message block的时候没问题么?
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-22 16:06 , Processed in 0.017112 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表