找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 9627|回复: 18

Proactor 自带例子 问题

[复制链接]
发表于 2008-7-15 22:25:35 | 显示全部楼层 |阅读模式
在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 掉.
请大家帮忙怎么解决.
  1. // test_end_event_loop.cpp,v 1.7 2004/05/05 18:59:34 shuston Exp
  2. // ============================================================================
  3. //
  4. // = FILENAME
  5. //     test_end_event_loop.cpp
  6. //
  7. // = DESCRITPTION
  8. //     This program tests the event loop mechanism of the
  9. //     Proactor. To end the event loop, threads that are blocked in
  10. //     waiting for completions are  woken up and the event loop comes
  11. //     to the end. This is tested in this program.
  12. //
  13. //     Threads are doing <run_event_loop> with/without time_out
  14. //     values and the main thread calls <end_event_loop>.
  15. //
  16. // = COMPILATION
  17. //     make
  18. //
  19. // = RUN
  20. //     ./test_end_event_loop
  21. //
  22. // = AUTHOR
  23. //     Alexander Babu Arulanthu <alex@cs.wustl.edu>
  24. //
  25. // =====================================================================
  26. #include "ace/OS_NS_unistd.h"
  27. #include "ace/Proactor.h"
  28. #include "ace/Task.h"
  29. #include "ace/WIN32_Proactor.h"
  30. #include "ace/POSIX_Proactor.h"
  31. #include "ace/OS_main.h"
  32. #if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || \
  33.      (defined (ACE_HAS_AIO_CALLS)) && !defined (ACE_POSIX_AIOCB_PROACTOR))
  34. // This only works on Win32 platforms and on Unix platforms supporting
  35. // POSIX aio calls.
  36. class My_Task: public ACE_Task <ACE_NULL_SYNCH>
  37. {
  38.   // = TITLE
  39.   //
  40.   //     Contains thread functions which execute event loops. Each
  41.   //     thread waits for a different signal.
  42.   //
  43. public:
  44.   // Constructor.
  45.   My_Task (void)
  46.     : time_flag_ (0)
  47.     {}
  48.   virtual ~My_Task (void) {}
  49.   // Destructor.
  50.   // If time_flag is zero do the eventloop indefinitely, otherwise do
  51.   // it for finite amount of time (13secs!!!).
  52.   int open (void *timed_event_loop)
  53.     {
  54.       // Set the local variable.
  55.       if (timed_event_loop == 0)
  56.         this->time_flag_ = 0;
  57.       else
  58.         this->time_flag_ = 1;
  59.       // Spawn the threads.
  60.       if (this->activate (THR_NEW_LWP, 5) == -1)
  61.         ACE_ERROR_RETURN ((LM_ERROR,
  62.                            "%N:%l:%p\n",
  63.                            "My_Task:open: <activate> failed"),
  64.                           -1);
  65.       return 0;
  66.     }
  67.   // Thread function.
  68.   int svc (void)
  69.     {
  70.       ACE_DEBUG ((LM_DEBUG,
  71.                   "(%P|%t):Starting svc routine\n"));
  72.       if (this->time_flag_)
  73.         {
  74.           ACE_DEBUG ((LM_DEBUG,
  75.                       "(%P|%t):Going to do *timed* <run_event_loop> \n"));
  76.           ACE_Time_Value run_time (13);
  77.           if (ACE_Proactor::instance ()->run_event_loop (run_time) == -1)
  78.             ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t):%p.\n",
  79.                                "<Proactor::run_event_loop> failed"),
  80.                               -1);
  81.         }
  82.       else
  83.         {
  84.           ACE_DEBUG ((LM_DEBUG,
  85.                       "(%P|%t):Going to do *indefinite* <run_event_loop> \n"));
  86.           if (ACE_Proactor::instance ()->run_event_loop () == -1)
  87.             ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t):%p.\n",
  88.                                "<Proactor::run_event_loop> failed"),
  89.                               -1);
  90.         }
  91.       return 0;
  92.     };
  93. private:
  94.   int time_flag_;
  95.   // If zero, indefinite event loop, otherwise timed event loop.
  96. };
  97. int
  98. ACE_TMAIN (int argc, ACE_TCHAR *argv [])
  99. {
  100.   ACE_UNUSED_ARG (argc);
  101.   ACE_UNUSED_ARG (argv);
  102.   ACE_DEBUG ((LM_DEBUG,
  103.               "(%P | %t):Test starts \n"));
  104.   // Let us get the singleton proactor created here. This is very
  105.   // important. This will mask the signal used in the Proactor masked
  106.   // for the main thread (and all the threads).
  107.   ACE_Proactor *proactor = ACE_Proactor::instance ();
  108.   ACE_UNUSED_ARG (proactor);
  109.   My_Task task1, task2;
  110.   // Test the indefinite run event loop.
  111.   if (task1.open (0) == -1)
  112.     ACE_ERROR_RETURN ((LM_ERROR,
  113.                        "%N:%l:(%P | %t):Failed to <open> the task\n"),
  114.                       1);
  115.   // Test the indefinite run event loop. Just pass a non-zero.
  116.   if (task2.open ((void *)&task2) == -1)
  117.     ACE_ERROR_RETURN ((LM_ERROR,
  118.                        "%N:%l:(%P | %t):Failed to <open> the task\n"),
  119.                       1);
  120.   // Give a gap.
  121.   ACE_OS::sleep (3);
  122.   // End the event loop.
  123.   if (ACE_Proactor::instance ()->end_event_loop () == -1)
  124.     ACE_ERROR_RETURN ((LM_ERROR,
  125.                        "%N:%l:(%P | %t):Failed to <end_event_loop>\n"),
  126.                       1);
  127.   ACE_Thread_Manager::instance ()->wait ();
  128.   ACE_DEBUG ((LM_DEBUG,
  129.               "(%P | %t):Test ends\n"));
  130.   return 0;
  131. }
  132. #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
  133. template class ACE_Task <ACE_NULL_SYNCH>;
  134. #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
  135. #pragma instantiate ACE_Task <ACE_NULL_SYNCH>
  136. #endif /* ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA */
  137. #else /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS && !ACE_POSIX_AIOCB_PROACTOR*/
  138. int
  139. main (int, char *[])
  140. {
  141.   ACE_DEBUG ((LM_DEBUG,
  142.               "This example cannot work with AIOCB_Proactor.\n"));
  143.   return 1;
  144. }
  145. #endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS && !ACE_POSIX_AIOCB_PROACTOR*/
复制代码
 楼主| 发表于 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 ();会不会因为这个而等待了,导致程序不能结束?


请大家帮帮忙,,急啊!!!
 楼主| 发表于 2008-7-15 22:26:34 | 显示全部楼层
这个是完全正常的程序行为,不是异常,不是程序的bug。所有人跑这个程序,都是这个结果。呵呵。
 楼主| 发表于 2008-7-15 22:26:43 | 显示全部楼层
如果要结束程序,需要使用一个Ctrl + C的响应中断。很简单的,ACE的例子里面有演示。
 楼主| 发表于 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文件.
 楼主| 发表于 2008-7-15 22:26:58 | 显示全部楼层
我说的不是强行结束,ACE的程序都是可以正常结束的。
 楼主| 发表于 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;
}
发表于 2008-8-3 19:27:35 | 显示全部楼层
可以不用ACE_Thread_Manager::instance ()->wait ();


task1.wait();
task2.wait();
代替
发表于 2008-8-3 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了吧。
发表于 2008-8-3 21:33:08 | 显示全部楼层
没有冲突。我所有的系统中,都是用ACE_Thread_Manager::instance ()的。你用法不对头。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

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

GMT+8, 2024-4-30 14:58 , Processed in 0.012573 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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