Doxygen changes
[ACE_TAO.git] / ACE / tests / Bug_2653_Regression_Test.cpp
blob8f8fe46943c3753bab5aa498f99aaeaf602ac630
2 //=============================================================================
3 /**
4 * @file Bug_2653_Regression_Test.cpp
6 * This bug occurs when schedule_wakeup is called for a handle that does
7 * not already have an event handler registered. This can happen quite
8 * legitimately in multithreaded applications where one thread schedules
9 * the wakeup while another thread is handling the closure of the
10 * connection and unregistering.
12 * @author Phil Mesnier <mesnier_p@ociweb.com>
14 //=============================================================================
17 #include "test_config.h"
18 #include "ace/OS_NS_string.h"
19 #include "ace/Reactor.h"
20 #include "ace/TP_Reactor.h"
21 #include "ace/Pipe.h"
22 #include "ace/ACE.h"
23 #include "ace/Task.h"
24 #include "ace/OS_NS_unistd.h"
28 static const char *message =
29 "Hello there! Hope you get this message";
31 class Watchdog : public ACE_Task_Base
33 public:
34 int svc (void);
35 int my_grp_;
38 int
39 Watchdog::svc (void)
41 ACE_OS::sleep (5);
42 // If we make it through the sleep and haven't been canceled, that
43 // means the process is hung.
44 if (!this->thr_mgr ()->testcancel (ACE_Thread::self ()))
45 ACE_ERROR ((LM_ERROR,
46 ACE_TEXT ("Watchdog slept without cancel - we're hung\n")));
47 return 0;
50 class Handler : public ACE_Event_Handler
52 public:
53 Handler (ACE_Reactor &reactor, bool close_other);
55 ~Handler();
57 int handle_input (ACE_HANDLE fd);
59 int handle_output (ACE_HANDLE fd);
61 ACE_Pipe pipe_;
62 ACE_Pipe other_pipe_;
65 Handler::Handler (ACE_Reactor &reactor, bool close_other)
66 : ACE_Event_Handler (&reactor)
68 // Create the pipe.
69 if (0 != this->other_pipe_.open () || 0 != this->pipe_.open())
71 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("pipe")));
73 else
75 // Register for all events.
76 if (0 != this->reactor ()->register_handler
77 (this->pipe_.read_handle (),
78 this,
79 ACE_Event_Handler::READ_MASK))
81 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("register")));
84 if (-1 == this->reactor ()->schedule_wakeup
85 (this->other_pipe_.write_handle(),
86 ACE_Event_Handler::WRITE_MASK))
88 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("Schedule")));
91 // closing the other pipe sets up the spinner error.
92 // leaving it open sets up the segv.
93 if (close_other)
94 this->other_pipe_.close();
98 Handler::~Handler (void)
100 this->other_pipe_.close();
101 this->pipe_.close ();
105 Handler::handle_output (ACE_HANDLE)
107 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Handler::handle_output\n")));
109 #if defined (__OpenBSD__) || defined (ACE_VXWORKS)
110 // All that we need written has been written, so don't
111 // call handle_output again.
112 this->reactor ()->mask_ops (this->pipe_.read_handle (),
113 ACE_Event_Handler::WRITE_MASK,
114 ACE_Reactor::CLR_MASK);
115 #endif /* __OpenBSD__ || ACE_VXWORKS */
117 return 0;
121 Handler::handle_input (ACE_HANDLE fd)
123 char buffer[BUFSIZ];
124 ssize_t result = ACE::recv (fd, buffer, sizeof buffer);
126 if (result != ssize_t (ACE_OS::strlen (message)))
127 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Handler recv'd %b bytes; expected %B\n"),
128 result, ACE_OS::strlen (message)));
129 buffer[result] = '\0';
131 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Handler::handle_input: %C\n"), buffer));
133 if (ACE_OS::strcmp (buffer, message) != 0)
134 ACE_ERROR ((LM_ERROR,
135 ACE_TEXT ("Handler text mismatch; received \"%C\"; ")
136 ACE_TEXT ("expected \"%C\"\n"),
137 buffer, message));
139 this->reactor ()->end_reactor_event_loop ();
140 return 0;
143 static void
144 test_for_crash (ACE_Reactor &reactor)
146 Handler handler (reactor, false);
148 // This should trigger a call to <handle_input>.
149 ssize_t result =
150 ACE::send_n (handler.pipe_.write_handle (),
151 message,
152 ACE_OS::strlen (message));
153 if (result != ssize_t (ACE_OS::strlen (message)))
154 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Handler sent %b bytes; should be %B\n"),
155 result, ACE_OS::strlen (message)));
157 reactor.run_reactor_event_loop ();
159 if (0 != reactor.remove_handler (handler.pipe_.read_handle (),
160 ACE_Event_Handler::ALL_EVENTS_MASK |
161 ACE_Event_Handler::DONT_CALL))
162 ACE_ERROR ((LM_ERROR,
163 ACE_TEXT ("%p\n"),
164 ACE_TEXT ("test_for_handler, remove pipe")));
166 if (0 == reactor.remove_handler (handler.other_pipe_.write_handle (),
167 ACE_Event_Handler::ALL_EVENTS_MASK |
168 ACE_Event_Handler::DONT_CALL))
169 ACE_ERROR ((LM_ERROR,
170 ACE_TEXT ("test_for_crash remove other_pipe succeeded ")
171 ACE_TEXT ("but shouldn't\n")));
174 static void
175 test_for_spin (ACE_Reactor &reactor)
177 Handler handler (reactor, true);
179 // This should trigger a call to <handle_input>.
180 ssize_t result =
181 ACE::send_n (handler.pipe_.write_handle (),
182 message,
183 ACE_OS::strlen (message));
184 if (result != ssize_t (ACE_OS::strlen (message)))
185 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Handler sent %b bytes; should be %B\n"),
186 result, ACE_OS::strlen (message)));
188 reactor.run_reactor_event_loop ();
190 if (0 != reactor.remove_handler (handler.pipe_.read_handle (),
191 ACE_Event_Handler::ALL_EVENTS_MASK |
192 ACE_Event_Handler::DONT_CALL))
193 ACE_ERROR ((LM_ERROR,
194 ACE_TEXT ("%p\n"),
195 ACE_TEXT ("test_for_spin, remove pipe")));
197 if (0 == reactor.remove_handler (handler.other_pipe_.write_handle (),
198 ACE_Event_Handler::ALL_EVENTS_MASK |
199 ACE_Event_Handler::DONT_CALL))
200 ACE_ERROR ((LM_ERROR,
201 ACE_TEXT ("test_for_spin remove other_pipe succeeded ")
202 ACE_TEXT ("but shouldn't\n")));
206 run_main (int, ACE_TCHAR *[])
208 ACE_START_TEST (ACE_TEXT ("Bug_2653_Regression_Test"));
210 ACE_TP_Reactor tp_reactor_impl;
211 ACE_Reactor tp_reactor (&tp_reactor_impl);
212 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Testing for crash\n")));
213 test_for_crash (tp_reactor);
214 // if that passes, start the watchdog. We don't need to wait
215 Watchdog wd;
216 wd.activate ();
217 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Testing for spin\n")));
218 test_for_spin(tp_reactor);
219 // If test_for_spin returns, all is well.
220 wd.thr_mgr ()->cancel_grp (wd.grp_id ());
221 wd.wait ();
223 ACE_END_TEST;
224 return 0;