Proactor 自带例子 问题
在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 掉.
请大家帮忙怎么解决.
// 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 arewoken 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*/
在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 ();会不会因为这个而等待了,导致程序不能结束?
请大家帮帮忙,,急啊!!! 这个是完全正常的程序行为,不是异常,不是程序的bug。所有人跑这个程序,都是这个结果。呵呵。 如果要结束程序,需要使用一个Ctrl + C的响应中断。很简单的,ACE的例子里面有演示。 谢谢 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文件. 我说的不是强行结束,ACE的程序都是可以正常结束的。 谢谢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;
} 可以不用ACE_Thread_Manager::instance ()->wait ();
用
task1.wait();
task2.wait();
代替 发现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了吧。 没有冲突。我所有的系统中,都是用ACE_Thread_Manager::instance ()的。你用法不对头。
页:
[1]
2