贝贝花花包包店,精品555皮具,钱夹,皮夹

字体:  

Proactor 自带例子 问题

peakzhang 发表于: 2008-7-15 22:25 来源: ACE 开发者

在ACE自带的例子中.D:\ACE_wrappers\examples\Reactor\Proactor
里面有个Proactor_End_Event_Loops. 运行是,结果正常,但是运行到
ACE_Thread_Manager::instance ()->wait (); 程序就停住了,并不能结束.
本人的运行环境: ACE - 5.5   ACE_AS_STATIC_LIBS  操作系统WINXP
在LINUX 2.6.9-5.EL 下试过也是一样.
之前在用 Reactor时也遇到过 ACE_Thread_Manager::instance ()->wait (); 时出错,导致 core 掉.
请大家帮忙怎么解决.

CODE:


// test_end_event_loop.cpp,v 1.7 2004/05/05 18:59:34 shuston Exp
// ============================================================================
//
// = FILENAME
//     test_end_event_loop.cpp
//
// = DESCRITPTION
//     This program tests the event loop mechanism of the
//     Proactor. To end the event loop, threads that are blocked in
//     waiting for completions are  woken up and the event loop comes
//     to the end. This is tested in this program.
//
//     Threads are doing <run_event_loop> with/without time_out
//     values and the main thread calls <end_event_loop>.
//
// = COMPILATION
//     make
//
// = RUN
//     ./test_end_event_loop
//
// = AUTHOR
//     Alexander Babu Arulanthu <alex@cs.wustl.edu>
//
// =====================================================================
#include "ace/OS_NS_unistd.h"
#include "ace/Proactor.h"
#include "ace/Task.h"
#include "ace/WIN32_Proactor.h"
#include "ace/POSIX_Proactor.h"
#include "ace/OS_main.h"
#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || \
     (defined (ACE_HAS_AIO_CALLS)) && !defined (ACE_POSIX_AIOCB_PROACTOR))
// This only works on Win32 platforms and on Unix platforms supporting
// POSIX aio calls.
class My_Task: public ACE_Task <ACE_NULL_SYNCH>
{
  // = TITLE
  //
  //     Contains thread functions which execute event loops. Each
  //     thread waits for a different signal.
  //
public:
  // Constructor.
  My_Task (void)
    : time_flag_ (0)
    {}

  virtual ~My_Task (void) {}
  // Destructor.
  // If time_flag is zero do the eventloop indefinitely, otherwise do
  // it for finite amount of time (13secs!!!).
  int open (void *timed_event_loop)
    {
      // Set the local variable.
      if (timed_event_loop == 0)
        this->time_flag_ = 0;
      else
        this->time_flag_ = 1;
      // Spawn the threads.
      if (this->activate (THR_NEW_LWP, 5) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "%N:%l:%p\n",
                           "My_Task:open: <activate> failed"),
                          -1);
      return 0;
    }
  // Thread function.
  int svc (void)
    {
      ACE_DEBUG ((LM_DEBUG,
                  "(%P|%t):Starting svc routine\n"));
      if (this->time_flag_)
        {
          ACE_DEBUG ((LM_DEBUG,
                      "(%P|%t):Going to do *timed* <run_event_loop> \n"));
          ACE_Time_Value run_time (13);
          if (ACE_Proactor::instance ()->run_event_loop (run_time) == -1)
            ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t):%p.\n",
                               "<Proactor::run_event_loop> failed"),
                              -1);
        }
      else
        {
          ACE_DEBUG ((LM_DEBUG,
                      "(%P|%t):Going to do *indefinite* <run_event_loop> \n"));
          if (ACE_Proactor::instance ()->run_event_loop () == -1)
            ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t):%p.\n",
                               "<Proactor::run_event_loop> failed"),
                              -1);
        }
      return 0;
    };
private:
  int time_flag_;
  // If zero, indefinite event loop, otherwise timed event loop.
};
int
ACE_TMAIN (int argc, ACE_TCHAR *argv [])
{
  ACE_UNUSED_ARG (argc);
  ACE_UNUSED_ARG (argv);
  ACE_DEBUG ((LM_DEBUG,
              "(%P | %t):Test starts \n"));
  // Let us get the singleton proactor created here. This is very
  // important. This will mask the signal used in the Proactor masked
  // for the main thread (and all the threads).
  ACE_Proactor *proactor = ACE_Proactor::instance ();
  ACE_UNUSED_ARG (proactor);
  My_Task task1, task2;
  // Test the indefinite run event loop.
  if (task1.open (0) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%N:%l:(%P | %t):Failed to <open> the task\n"),
                      1);
  // Test the indefinite run event loop. Just pass a non-zero.
  if (task2.open ((void *)&task2) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%N:%l:(%P | %t):Failed to <open> the task\n"),
                      1);
  // Give a gap.
  ACE_OS::sleep (3);
  // End the event loop.
  if (ACE_Proactor::instance ()->end_event_loop () == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%N:%l:(%P | %t):Failed to <end_event_loop>\n"),
                      1);
  ACE_Thread_Manager::instance ()->wait ();
  ACE_DEBUG ((LM_DEBUG,
              "(%P | %t):Test ends\n"));
  return 0;
}
#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
template class ACE_Task <ACE_NULL_SYNCH>;
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
#pragma instantiate ACE_Task <ACE_NULL_SYNCH>
#endif /* ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA */
#else /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS && !ACE_POSIX_AIOCB_PROACTOR*/
int
main (int, char *[])
{
  ACE_DEBUG ((LM_DEBUG,
              "This example cannot work with AIOCB_Proactor.\n"));
  return 1;
}
#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS && !ACE_POSIX_AIOCB_PROACTOR*/

最新回复

peakzhang at 2008-7-15 22:26:22
在ACE_Proactor里面,在默认,超时时是使用 ACE_Timer_Heap timer queue mechamism来分发事件,在
创建 ACE_Proactor时 创建了一个线程, 在proactor.cpp :349 行
  // Set the timer queue.
this->timer_queue (tq);
// Create the timer handler
ACE_NEW (this->timer_handler_,
ACE_Proactor_Timer_Handler (*this));
// Activate <timer_handler>.
if (this->timer_handler_->activate (THR_NEW_LWP) == -1)
   
结合本例子,跟踪时,发现该线程 在proactor.cpp : 146行 等待了,
      else
    // The timer queue has no entries, so wait indefinitely.
    result = this->timer_event_.wait ();
而主线程ACE_Thread_Manager::instance ()->wait ();会不会因为这个而等待了,导致程序不能结束?


请大家帮帮忙,,急啊!!!
peakzhang at 2008-7-15 22:26:34
这个是完全正常的程序行为,不是异常,不是程序的bug。所有人跑这个程序,都是这个结果。呵呵。
peakzhang at 2008-7-15 22:26:43
如果要结束程序,需要使用一个Ctrl + C的响应中断。很简单的,ACE的例子里面有演示。
peakzhang at 2008-7-15 22:26:50
谢谢 winston 的帮助.你的意思是

定义捕捉信号量类,handle_single 然后强行exit()程序 ?

使用了另外的方法也可以,不过实际可能不会这样用.

把所有创建的线程都归到一个组里面.

static int g_nGrpID = 10;

activate (THR_NEW_LWP|THR_JOINABLE , 3,0,ACE_DEFAULT_THREAD_PRIORITY,g_nGrpID)

在ACE_TMAIN 里面 使用:

ACE_Thread_Manager::instance ()->wait_grp(g_nGrpID);

这样就可以正常结束了.

正常结束程序很重要,析构类,最少不会有core文件.
peakzhang at 2008-7-15 22:26:58
我说的不是强行结束,ACE的程序都是可以正常结束的。
peakzhang at 2008-7-15 22:37:13
谢谢winston版主的关注,

你的意思是 发送一个 SIGINT /*中断*/信号什么的终断程序? 我试过直接 ctrl+c 关闭程序,发现自己定义的类是没有正常析构的.当然 ACE_Thread_Manager类里面是正常析够的.

有没有更好的解决办法?

我也试过加个信号处理类,但是捕捉到 SIGINT后,怎么样解除 ACE_Thread_Manager的wait();

virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0)
{
  ACE_TRACE (ACE_TEXT ("MySignalHandler::handle_signal"));

  // Make sure the right handler was called back..
  // ACE_ASSERT(signum == this->signum_);
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("信号%d occured\n"), signum));

  ACE_Reactor::instance()->end_reactor_event_loop();
  //捕捉到CTRL + C 后这里需要如何处理???? 解除ACE_Thread_Manager的wait(),或者Proactor产生的线程 让程序正常结束?

  return 0;
}
wishel at 2008-8-03 19:27:35
可以不用ACE_Thread_Manager::instance ()->wait ();


task1.wait();
task2.wait();
代替
wishel at 2008-8-03 20:50:42
发现proactor和ACE_Thread_Manager::instance ()->wait ()有冲突

int
ACE_TMAIN (int argc, ACE_TCHAR *argv [])
{
  ACE_DEBUG ((LM_DEBUG,
              "(%P | %t):Test begins\n"));
  ACE_Proactor::instance ();
  ACE_Thread_Manager::instance ()->wait ();
  ACE_DEBUG ((LM_DEBUG,
              "(%P | %t):bye!\n"));
  return 0;
}
就不会走到结束,如果把ACE_Proactor::instance ();这一行注释掉就可以。
按道理不应该这样,应该算是bug了吧。
winston at 2008-8-03 21:33:08
没有冲突。我所有的系统中,都是用ACE_Thread_Manager::instance ()的。你用法不对头。
wishel at 2008-8-03 23:26:00
int ACE_TMAIN (int argc, ACE_TCHAR *argv []) {
  ACE_Proactor::instance ();
  ACE_Thread_Manager::instance ()->wait ();
  return 0;
}
这个跑不完

int ACE_TMAIN (int argc, ACE_TCHAR *argv []) {
  ACE_Thread_Manager::instance ()->wait ();
  return 0;
}
这个就能跑完
你说有没有冲突?
这么简单的程序还说我用法不对头?我根本就没用那个proactor,就是产生了一个singleton的实例而已
wishel at 2008-8-03 23:32:57
或者把proactor换成reactor
int ACE_TMAIN (int argc, ACE_TCHAR *argv [])
{
  ACE_Reactor::instance ();
  ACE_Thread_Manager::instance ()->wait ();
  return 0;
}
也能顺利跑完,可以确定是一个bug
产生一个proactor的singleton实例(第一次用所以新产生),不应该产生任何新线程,更不应该让ACE_Thread_Manager::instance ()->wait ()阻塞,这是不符合proactor的语义的。
wishel at 2008-8-04 12:04:10
int ACE_TMAIN (int argc, ACE_TCHAR *argv [])
{
  ACE_WIN32_Proactor win32_proactor (0, 0); //win32下的缺省ACE_Proactor_Impl
  ACE_Thread_Manager::instance ()->wait ();

  //can not reach here!!!
  return 0;
}
也不行,我这边没有unix环境,不知道其他的imp行不行

[ 本帖最后由 wishel 于 2008-8-4 12:05 编辑 ]
winston at 2008-8-04 12:37:10
你先搞明白:ACE_Thread_Manager::instance ()->wait ();
是什么意思,再来问大家。
其实ACE_Thread_Manager::instance ()一般用wait_task功能。wait是等所有线程退出。
如:
tm->wait_task (&m_task_obj);
wishel at 2008-8-04 12:48:57
晕。。我不是在问大家,我是在回答楼主问题
恰恰是你没搞明白ACE_Thread_Manager::instance ()->wait ()是什么意思
建议你再去看书,C++NPv1 p189(英文版),表里说的很明白了

还有在examples\Reactor\Proactor下面还有一个测试程序test_multiple_loops.cpp,有同样的问题,最后一行romove是执行不到的
wishel at 2008-8-04 12:50:39
作为版主回答问题要负责任,这么简单的问题,自己亲自调一下就很明白,这个程序很简单也花不了几分钟时间。然后再来回答网友提问,特别是有争议的情况下。
winston at 2008-8-04 13:30:50
谢谢批评。
版主不是神,也没义务做那么多FREE的事情。大家只是交流和沟通而已。
此贴是旧帖“翻新”,我理解有误,不好意思。你的回答是正确的。最好不要用wait,我也是用task代替。
用wait,必须有外面的中断措施。
wishel at 2008-8-04 20:01:53
抱歉我说的重了点,版主辛苦了,希望以后多交流经验。
xenium_lee at 2008-9-16 16:23:51
我也碰到了,我觉得是ACE_WIN32_Proactor构造函数中this->get_asynch_pseudo_task ().start (); 这一句派生了一个线程,异步connect用的。这个线程在ACE_WIN32_Proactor析构函数中会终止,所以只需要等待运行proactor循环的线程。
ACE_Thread_Manager::instance ()->join(t_id), t_id是spwan的返回值。