diff options
Diffstat (limited to 'ACE/tests/Reactor_Exceptions_Test.cpp')
-rw-r--r-- | ACE/tests/Reactor_Exceptions_Test.cpp | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/ACE/tests/Reactor_Exceptions_Test.cpp b/ACE/tests/Reactor_Exceptions_Test.cpp new file mode 100644 index 00000000000..ad39ee0cf09 --- /dev/null +++ b/ACE/tests/Reactor_Exceptions_Test.cpp @@ -0,0 +1,228 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Reactor_Exceptions_Test.cpp +// +// = DESCRIPTION +// This is a test that makes sure the <ACE_Reactor> works +// correctly in the face of C++ exceptions and threads. +// +// = AUTHOR +// Luca Priorelli <lucapri@mbox.vol.it> and Douglas C. Schmidt <schmidt@cs.wustl.edu> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Reactor.h" +#include "ace/SOCK_Dgram.h" +#include "ace/INET_Addr.h" +#include "ace/Thread_Manager.h" + +ACE_RCSID(tests, Reactor_Exceptions_Test, "$Id$") + +#if defined (ACE_HAS_EXCEPTIONS) + +#if defined (ACE_WIN32) && defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) +static void +throw_exception (void) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) throw exception\n"))); + + // Cause a Win32 structured exception. + *(char *) 0 = 0; +} +#else +// Just need a simple exception class. +class Except {}; + +static void +throw_exception (void) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) throw exception\n"))); + throw Except (); +} +#endif /* ACE_WIN32 && ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + +class My_Handler : public ACE_Event_Handler, public ACE_SOCK_Dgram +{ +public: + My_Handler (const ACE_INET_Addr &local_addr); + + virtual ACE_HANDLE get_handle (void) const; + virtual int handle_input (ACE_HANDLE handle); +}; + +My_Handler::My_Handler (const ACE_INET_Addr &local_addr) + : ACE_SOCK_Dgram (local_addr) +{ +} + +ACE_HANDLE +My_Handler::get_handle (void) const +{ + return ACE_SOCK_Dgram::get_handle (); +} + +int +My_Handler::handle_input (ACE_HANDLE) +{ + ACE_TCHAR buf[BUFSIZ]; + ACE_INET_Addr from_addr; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Activity occurred on handle %d!\n"), + ACE_SOCK_Dgram::get_handle ())); + + ssize_t n = ACE_SOCK_Dgram::recv (buf, + sizeof buf, + from_addr); + if (n == -1) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("handle_input"))); + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("got buf = %s\n"), + buf)); + + throw_exception (); + return 0; +} + +class My_Reactor : public ACE_Reactor +{ +public: + virtual int handle_events (ACE_Time_Value *max_wait_time) + { + int ret = 0; + + try + { +# if defined (ACE_WIN32) && defined (__BORLANDC__) + // BCB does not catch structured exceptions with catch (...). + // Actually, the ANSI spec says that system exceptions are not + // supposed to be caught with catch. Borland may add this, and + // make it "switchable" in the future... + try + { +# endif /* defined (ACE_WIN32 && __BORLANDC__) */ + + ret = ACE_Reactor::handle_events (max_wait_time); + +# if defined (ACE_WIN32) && defined (__BORLANDC__) + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + // Probably should handle the details of the exception + // and throw something that represents the structured exception + throw "Win32 Structured Exception"; + } +# endif /* defined (ACE_WIN32 &&__BORLANDC__) */ + } + catch (...) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT (" (%t) catch exception\n"))); + ret = -1; + // do your thing, etc. + } + return ret; + } + + virtual int handle_events (ACE_Time_Value &max_wait_time) + { + return this->handle_events (&max_wait_time); + } +}; + +#if defined (ACE_HAS_THREADS) +static int +worker (void) +{ + ACE_Reactor::instance ()->owner (ACE_OS::thr_self ()); + + for (;;) + if (ACE_Reactor::instance ()->handle_events () == -1) + { + ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%t) exception return\n"))); + break; + } + + return 0; +} +#endif /* ACE_HAS_THREADS */ + +#endif /* ACE_HAS_EXCEPTIONS */ + +int +run_main (int argc, ACE_TCHAR *argv[]) +{ + ACE_START_TEST (ACE_TEXT ("Reactor_Exceptions_Test")); + +#if defined (ACE_HAS_EXCEPTIONS) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Starting tracing\n"))); + + u_short port = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT; + + ACE_INET_Addr local_addr (port); + ACE_INET_Addr remote_addr (port, ACE_LOCALHOST, PF_INET); + My_Reactor reactor; + + ACE_Reactor::instance (&reactor); + ACE_Thread_Manager *thr_mgr = ACE_Thread_Manager::instance (); + + { + // Make sure handler gets cleaned up before reactor by putting it in its + // own scope + My_Handler handler (local_addr); + + + if (ACE_Reactor::instance ()->register_handler + (&handler, + ACE_Event_Handler::READ_MASK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("register_handler")), + -1); + +#if defined (ACE_HAS_THREADS) + thr_mgr->spawn (ACE_THR_FUNC (worker)); +#else + // Need to figure out how to implement this test. + ACE_ERROR ((LM_INFO, + ACE_TEXT ("threads not supported on this platform\n"))); +#endif /* ACE_HAS_THREADS */ + + ACE_SOCK_Dgram dgram (ACE_sap_any_cast (ACE_INET_Addr &), PF_INET); + + for (size_t i = 0; i < ACE_MAX_ITERATIONS; i++) + dgram.send (ACE_TEXT ("Hello"), + sizeof (ACE_TEXT ("Hello")), + remote_addr); + // Barrier to wait for the other thread to return. + thr_mgr->wait (); + + handler.close (); + dgram.close (); + } + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT (" (%t) exiting main\n"))); +#else + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + ACE_ERROR ((LM_INFO, + ACE_TEXT ("C++ exception support not enabled on this platform\n"))); +#endif /* ACE_HAS_EXCEPTIONS */ + + ACE_END_TEST; + return 0; +} |