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"
22 #include "ace/Dev_Poll_Reactor.h"
24 #include "ace/Auto_Ptr.h"
29 int overall_result
= 0;
31 // ------------------------------------------------------------
33 class Bogus_Handler
: public ACE_Event_Handler
37 Bogus_Handler (ACE_Reactor
* reactor
,
38 ACE_HANDLE read_handle
,
39 bool & okay_to_close
);
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);
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
,
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)
77 Bogus_Handler::get_handle (void) const
79 return this->read_handle_
;
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")),
94 Bogus_Handler::handle_close (ACE_HANDLE
,
97 if (this->okay_to_close_
)
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")),
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
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;
130 virtual ~Bad_Handler (void);
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;
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)
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)
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 (),
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)
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)
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
,
234 if (this->handle_close_called_
)
238 ACE_ERROR_RETURN ((LM_ERROR
,
239 ACE_TEXT ("Bad_Handler::handle_close() called ")
240 ACE_TEXT ("more than once\n")),
244 this->handle_close_called_
= true;
250 Bad_Handler::handle_input_result (void) const
253 (this->suspension_test_
255 // Attempt to force reactor to resume the handle after the
259 // Attempt to force the new event handler to be removed from the
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
,
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")),
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
303 size_t bytes_transferred
= 0;
304 ssize_t
const result
=
305 ACE::send_n (write_handle
,
312 || bytes_transferred
!= len
)
314 ACE_ERROR_RETURN ((LM_ERROR
,
316 ACE_TEXT ("Unable to send data")),
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")));
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.
345 int const result
= reactor
.handle_events (&timeout
);
350 ACE_ERROR ((LM_ERROR
,
351 ACE_TEXT ("Unexpectedly dispatched an event\n")));
357 ACE_ERROR ((LM_ERROR
,
358 ACE_TEXT ("Event loop failed unexpectedly\n")));
367 // ------------------------------------------------------------
369 typedef auto_ptr
<ACE_Reactor_Impl
> (*reactor_factory_type
) (void);
371 auto_ptr
<ACE_Reactor_Impl
>
372 dev_poll_reactor_factory (void)
375 ACE_TEXT ("Creating ACE_Dev_Poll_Reactor.\n")));
377 return auto_ptr
<ACE_Reactor_Impl
> (new ACE_Dev_Poll_Reactor
);
380 // ------------------------------------------------------------
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
=
402 + sizeof (suspension_test
) / sizeof (suspension_test
[0]);
404 for (bool const * i
= begin
; i
!= end
; ++i
)
406 bool const suspension_test
= *i
;
411 ACE_TEXT ("** Running suspension test **\n")));
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;
427 if (the_pipe
.open () != 0
428 || register_handler (&reactor
,
429 the_pipe
.read_handle (),
431 suspension_test
) != 0
432 || send_data (the_pipe
.write_handle ()) != 0
433 || handle_events (reactor
, okay_to_close
) != 0)
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")));
466 ACE_TEXT ("Test passed.\n")));
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")));
482 #endif /* ACE_HAS_EVENT_POLL || ACE_HAS_DEV_POLL */