Doxygen changes
[ACE_TAO.git] / ACE / tests / Reactor_Remove_Resume_Test_Dev_Poll.cpp
blob083dda5e5ff223969a28d176c5fa6ff12a3641d1
1 /**
2 * @file Reactor_Remove_Resume_Test_Dev_Poll.cpp
4 * This test verifies that ACE reactors only remove or resume the event
5 * handler used during an upcall, not another with same handle value.
6 * There is are least one case where the event handler can change
7 * during an upcall. The event handler could be removed by another
8 * thread, and a new one is registered for a handle of the same value
9 * (e.g. closed and then reopened) during an upcall. "Misbehaved"
10 * event handlers could also cause this problem by closing and
11 * deregistering the event handler during an upcall.
13 * @author Ossama Othman
17 #include "test_config.h"
19 #if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL)
20 #include "ace/Reactor.h"
21 #include "ace/ACE.h"
22 #include "ace/Dev_Poll_Reactor.h"
23 #include "ace/Pipe.h"
24 #include "ace/Auto_Ptr.h"
26 #include <algorithm>
27 #include <functional>
29 int overall_result = 0;
31 // ------------------------------------------------------------
33 class Bogus_Handler : public ACE_Event_Handler
35 public:
37 Bogus_Handler (ACE_Reactor * reactor,
38 ACE_HANDLE read_handle,
39 bool & okay_to_close);
41 protected:
43 virtual ~Bogus_Handler (void);
45 virtual ACE_HANDLE get_handle (void) const;
46 virtual int handle_input (ACE_HANDLE handle);
47 virtual int handle_close (ACE_HANDLE handle,
48 ACE_Reactor_Mask close_mask);
49 virtual int resume_handler (void);
51 private:
53 ACE_HANDLE const read_handle_;
55 // If the reactor closes the event handler before it gets the okay,
56 // we will issue an error.
57 bool & okay_to_close_;
61 Bogus_Handler::Bogus_Handler (ACE_Reactor * reactor,
62 ACE_HANDLE read_handle,
63 bool & okay_to_close)
64 : ACE_Event_Handler (reactor)
65 , read_handle_ (read_handle)
66 , okay_to_close_ (okay_to_close)
68 this->reference_counting_policy ().value (
69 ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
72 Bogus_Handler::~Bogus_Handler (void)
76 ACE_HANDLE
77 Bogus_Handler::get_handle (void) const
79 return this->read_handle_;
82 int
83 Bogus_Handler::handle_input (ACE_HANDLE)
85 // This event handler should have been suspended, meaning it should
86 // not have received any events.
87 ACE_ERROR_RETURN ((LM_ERROR,
88 ACE_TEXT ("Bogus_Handler received an ")
89 ACE_TEXT ("unexpected event.\n")),
90 -1);
93 int
94 Bogus_Handler::handle_close (ACE_HANDLE,
95 ACE_Reactor_Mask)
97 if (this->okay_to_close_)
98 return 0;
100 overall_result = -1;
102 // This event handler is being closed by the reactor unexpectedly.
103 ACE_ERROR_RETURN ((LM_ERROR,
104 ACE_TEXT ("Bogus_Handler unexpectedly closed\n")),
105 -1);
109 Bogus_Handler::resume_handler (void)
111 // We don't want the reactor to resume this event handler.
112 return ACE_APPLICATION_RESUMES_HANDLER;
115 // ------------------------------------------------------------
117 class Bad_Handler : public ACE_Event_Handler
119 public:
121 Bad_Handler (ACE_Reactor * reactor,
122 ACE_HANDLE read_handle,
123 bool & okay_to_close,
124 bool suspension_test);
126 ACE_HANDLE write_handle (void) const;
128 protected:
130 virtual ~Bad_Handler (void);
132 private:
134 virtual ACE_HANDLE get_handle (void) const;
135 virtual int handle_input (ACE_HANDLE handle);
136 virtual int handle_close (ACE_HANDLE handle,
137 ACE_Reactor_Mask close_mask);
139 int handle_input_result (void) const;
141 private:
143 ACE_HANDLE const read_handle_;
145 bool handle_close_called_;
147 // Passed on to the Bogus_Handler constructor. Not used by the
148 // Bad_Handler, otherwise.
149 bool & okay_to_close_;
151 // Are we running the event handler suspension or removal test?
152 bool suspension_test_;
156 Bad_Handler::Bad_Handler (ACE_Reactor * reactor,
157 ACE_HANDLE read_handle,
158 bool & okay_to_close,
159 bool suspension_test)
160 : ACE_Event_Handler (reactor)
161 , read_handle_ (read_handle)
162 , handle_close_called_ (false)
163 , okay_to_close_ (okay_to_close)
164 , suspension_test_ (suspension_test)
166 this->reference_counting_policy ().value (
167 ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
171 Bad_Handler::~Bad_Handler (void)
175 ACE_HANDLE
176 Bad_Handler::get_handle (void) const
178 return this->read_handle_;
182 Bad_Handler::handle_input (ACE_HANDLE handle)
184 // Remove ourselves from the reactor, and trigger a different one
185 // with the same handle to be registered.
186 if (this->reactor ()->remove_handler (handle,
187 ACE_Event_Handler::READ_MASK) != 0)
189 overall_result = -1;
191 ACE_ERROR_RETURN ((LM_ERROR,
192 ACE_TEXT ("Unable to remove Bad_Handler ")
193 ACE_TEXT ("from reactor\n")),
197 ACE_Event_Handler_var bogus_handler (
198 new Bogus_Handler (this->reactor (),
199 handle,
200 this->okay_to_close_));
202 // Register and suspend a new handler.
203 if (this->reactor ()->register_handler (handle,
204 bogus_handler.handler (),
205 ACE_Event_Handler::READ_MASK) != 0
206 || this->reactor ()->suspend_handler (handle) != 0)
208 overall_result = -1;
210 ACE_ERROR_RETURN ((LM_ERROR,
211 ACE_TEXT ("Unable to register or suspend ")
212 ACE_TEXT ("Bogus_Handler\n")),
216 // Make sure a read event exists for dispatching during the next
217 // event loop iteration.
218 if (this->reactor ()->schedule_wakeup (handle,
219 ACE_Event_Handler::READ_MASK) == -1)
221 overall_result = -1;
223 ACE_ERROR ((LM_ERROR,
224 ACE_TEXT ("Wakeup scheduling failed\n")));
227 return this->handle_input_result ();
231 Bad_Handler::handle_close (ACE_HANDLE,
232 ACE_Reactor_Mask)
234 if (this->handle_close_called_)
236 overall_result = -1;
238 ACE_ERROR_RETURN ((LM_ERROR,
239 ACE_TEXT ("Bad_Handler::handle_close() called ")
240 ACE_TEXT ("more than once\n")),
241 -1);
244 this->handle_close_called_ = true;
246 return 0;
250 Bad_Handler::handle_input_result (void) const
252 return
253 (this->suspension_test_
255 // Attempt to force reactor to resume the handle after the
256 // upcall completes.
259 // Attempt to force the new event handler to be removed from the
260 // reactor.
261 : -1);
264 // ------------------------------------------------------------
266 register_handler (ACE_Reactor * reactor,
267 ACE_HANDLE read_handle,
268 bool & okay_to_close,
269 bool suspension_test)
271 ACE_Event_Handler_var bad_handler (new Bad_Handler (reactor,
272 read_handle,
273 okay_to_close,
274 suspension_test));
276 // Register for read events.
277 if (reactor->register_handler (bad_handler.handler (),
278 ACE_Event_Handler::READ_MASK) != 0)
280 ACE_ERROR_RETURN ((LM_ERROR,
281 ACE_TEXT ("Unable to register Bad_Handler with ")
282 ACE_TEXT ("reactor\n")),
283 -1);
286 return 0;
289 // ------------------------------------------------------------
292 send_data (ACE_HANDLE write_handle)
294 char const foo[] = "foo";
295 size_t const len = sizeof (foo); // We want the number of bytes, not
296 // the number of characters.
298 ACE_Time_Value const timeout (2);
300 // Trigger a read event on the pipe handle. This shouldn't timeout
301 // since the pipe should be able to hold such a small amount of
302 // data.
303 size_t bytes_transferred = 0;
304 ssize_t const result =
305 ACE::send_n (write_handle,
306 foo,
307 len,
308 &timeout, // timeout
309 &bytes_transferred);
311 if (result == -1
312 || bytes_transferred != len)
314 ACE_ERROR_RETURN ((LM_ERROR,
315 ACE_TEXT ("%p\n"),
316 ACE_TEXT ("Unable to send data")),
317 -1);
320 return 0;
323 // ------------------------------------------------------------
326 handle_events (ACE_Reactor & reactor,
327 bool & okay_to_close)
329 ACE_Time_Value timeout (2);
331 // Only one event handler should have been dispatched.
332 if (reactor.handle_events (&timeout) != 1)
334 ACE_ERROR ((LM_ERROR,
335 ACE_TEXT ("Initial event dispatch failed\n")));
337 else
339 okay_to_close = true;
341 // Run the event loop again in an attempt to make the reactor
342 // dispatch the newly registered event handler. No events
343 // should be dispatched.
344 timeout.sec (2);
345 int const result = reactor.handle_events (&timeout);
348 if (result > 0)
350 ACE_ERROR ((LM_ERROR,
351 ACE_TEXT ("Unexpectedly dispatched an event\n")));
353 else if (result < 0)
355 overall_result = -1;
357 ACE_ERROR ((LM_ERROR,
358 ACE_TEXT ("Event loop failed unexpectedly\n")));
360 else
361 return 0;
364 return -1;
367 // ------------------------------------------------------------
369 typedef auto_ptr<ACE_Reactor_Impl> (*reactor_factory_type) (void);
371 auto_ptr<ACE_Reactor_Impl>
372 dev_poll_reactor_factory (void)
374 ACE_DEBUG ((LM_INFO,
375 ACE_TEXT ("Creating ACE_Dev_Poll_Reactor.\n")));
377 return auto_ptr<ACE_Reactor_Impl> (new ACE_Dev_Poll_Reactor);
380 // ------------------------------------------------------------
382 * @struct Caller
384 * @brief Reactor test execution functor.
386 * Reactor test execution functor.
388 struct Run_Test : public std::unary_function<reactor_factory_type, void>
390 /// Function call operator overload.
391 void operator() (reactor_factory_type factory)
393 bool const suspension_test[] =
395 true, // Run suspension test.
396 false // Run removal test.
399 bool const * const begin = suspension_test;
400 bool const * const end =
401 suspension_test
402 + sizeof (suspension_test) / sizeof (suspension_test[0]);
404 for (bool const * i = begin; i != end; ++i)
406 bool const suspension_test = *i;
408 if (suspension_test)
410 ACE_DEBUG ((LM_INFO,
411 ACE_TEXT ("** Running suspension test **\n")));
413 else
415 ACE_DEBUG ((LM_INFO,
416 ACE_TEXT ("** Running removal test **\n")));
419 auto_ptr<ACE_Reactor_Impl> the_factory (factory ());
420 ACE_Reactor reactor (the_factory.get ());
422 // In this test, it's only okay to close the Bogus_Handler
423 // when the reactor is destroyed.
424 bool okay_to_close = false;
426 ACE_Pipe the_pipe;
427 if (the_pipe.open () != 0
428 || register_handler (&reactor,
429 the_pipe.read_handle (),
430 okay_to_close,
431 suspension_test) != 0
432 || send_data (the_pipe.write_handle ()) != 0
433 || handle_events (reactor, okay_to_close) != 0)
435 overall_result = -1;
438 okay_to_close = true;
440 ACE_DEBUG ((LM_INFO, ACE_TEXT ("\n"))); // For log aesthetics.
445 // ------------------------------------------------------------
448 run_main (int, ACE_TCHAR *[])
450 ACE_START_TEST (ACE_TEXT ("Reactor_Remove_Resume_Test_Dev_Poll"));
452 static reactor_factory_type const factories[] =
454 dev_poll_reactor_factory
457 static size_t const factory_count = sizeof (factories) / sizeof (factories[0]);
459 std::for_each (factories, factories + factory_count, Run_Test ());
461 if (overall_result != 0)
462 ACE_ERROR ((LM_ERROR,
463 ACE_TEXT ("Test failed.\n")));
464 else
465 ACE_ERROR ((LM_INFO,
466 ACE_TEXT ("Test passed.\n")));
468 ACE_END_TEST;
470 return overall_result;
472 #else /* ACE_HAS_EVENT_POLL || ACE_HAS_DEV_POLL */
474 run_main (int, ACE_TCHAR *[])
476 ACE_START_TEST (ACE_TEXT ("Reactor_Remove_Resume_Test_Dev_Poll"));
477 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Dev_Poll_Reactor is not supported in this build\n")));
478 ACE_END_TEST;
480 return 0;
482 #endif /* ACE_HAS_EVENT_POLL || ACE_HAS_DEV_POLL */