2 * @file Reactor_Remove_Resume_Test.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
16 #include "test_config.h"
17 #include "ace/Reactor.h"
18 #include "ace/TP_Reactor.h"
25 int overall_result
= 0;
27 // ------------------------------------------------------------
29 class Bogus_Handler
: public ACE_Event_Handler
32 Bogus_Handler (ACE_Reactor
* reactor
,
33 ACE_HANDLE read_handle
,
34 bool & okay_to_close
);
37 ~Bogus_Handler () override
;
39 ACE_HANDLE
get_handle () const override
;
40 int handle_input (ACE_HANDLE handle
) override
;
41 int handle_close (ACE_HANDLE handle
,
42 ACE_Reactor_Mask close_mask
) override
;
43 int resume_handler () override
;
46 ACE_HANDLE
const read_handle_
;
48 // If the reactor closes the event handler before it gets the okay,
49 // we will issue an error.
50 bool & okay_to_close_
;
53 Bogus_Handler::Bogus_Handler (ACE_Reactor
* reactor
,
54 ACE_HANDLE read_handle
,
56 : ACE_Event_Handler (reactor
)
57 , read_handle_ (read_handle
)
58 , okay_to_close_ (okay_to_close
)
60 this->reference_counting_policy ().value (
61 ACE_Event_Handler::Reference_Counting_Policy::ENABLED
);
64 Bogus_Handler::~Bogus_Handler ()
69 Bogus_Handler::get_handle () const
71 return this->read_handle_
;
75 Bogus_Handler::handle_input (ACE_HANDLE
)
77 // This event handler should have been suspended, meaning it should
78 // not have received any events.
79 ACE_ERROR_RETURN ((LM_ERROR
,
80 ACE_TEXT ("Bogus_Handler received an ")
81 ACE_TEXT ("unexpected event.\n")),
86 Bogus_Handler::handle_close (ACE_HANDLE
,
89 if (this->okay_to_close_
)
94 // This event handler is being closed by the reactor unexpectedly.
95 ACE_ERROR_RETURN ((LM_ERROR
,
96 ACE_TEXT ("Bogus_Handler unexpectedly closed\n")),
101 Bogus_Handler::resume_handler ()
103 // We don't want the reactor to resume this event handler.
104 return ACE_APPLICATION_RESUMES_HANDLER
;
107 // ------------------------------------------------------------
109 class Bad_Handler
: public ACE_Event_Handler
112 Bad_Handler (ACE_Reactor
* reactor
,
113 ACE_HANDLE read_handle
,
114 bool & okay_to_close
,
115 bool suspension_test
);
117 ACE_HANDLE
write_handle () const;
120 ~Bad_Handler () override
;
123 ACE_HANDLE
get_handle () const override
;
124 int handle_input (ACE_HANDLE handle
) override
;
125 int handle_close (ACE_HANDLE handle
,
126 ACE_Reactor_Mask close_mask
) override
;
128 int handle_input_result () const;
131 ACE_HANDLE
const read_handle_
;
133 bool handle_close_called_
;
135 // Passed on to the Bogus_Handler constructor. Not used by the
136 // Bad_Handler, otherwise.
137 bool & okay_to_close_
;
139 // Are we running the event handler suspension or removal test?
140 bool suspension_test_
;
143 Bad_Handler::Bad_Handler (ACE_Reactor
* reactor
,
144 ACE_HANDLE read_handle
,
145 bool & okay_to_close
,
146 bool suspension_test
)
147 : ACE_Event_Handler (reactor
)
148 , read_handle_ (read_handle
)
149 , handle_close_called_ (false)
150 , okay_to_close_ (okay_to_close
)
151 , suspension_test_ (suspension_test
)
153 this->reference_counting_policy ().value (
154 ACE_Event_Handler::Reference_Counting_Policy::ENABLED
);
157 Bad_Handler::~Bad_Handler ()
162 Bad_Handler::get_handle () const
164 return this->read_handle_
;
168 Bad_Handler::handle_input (ACE_HANDLE handle
)
170 // Remove ourselves from the reactor, and trigger a different one
171 // with the same handle to be registered.
172 if (this->reactor ()->remove_handler (handle
,
173 ACE_Event_Handler::READ_MASK
) != 0)
177 ACE_ERROR_RETURN ((LM_ERROR
,
178 ACE_TEXT ("Unable to remove Bad_Handler ")
179 ACE_TEXT ("from reactor\n")),
183 ACE_Event_Handler_var
bogus_handler (
184 new Bogus_Handler (this->reactor (),
186 this->okay_to_close_
));
188 // Register and suspend a new handler.
189 if (this->reactor ()->register_handler (handle
,
190 bogus_handler
.handler (),
191 ACE_Event_Handler::READ_MASK
) != 0
192 || this->reactor ()->suspend_handler (handle
) != 0)
196 ACE_ERROR_RETURN ((LM_ERROR
,
197 ACE_TEXT ("Unable to register or suspend ")
198 ACE_TEXT ("Bogus_Handler\n")),
202 // Make sure a read event exists for dispatching during the next
203 // event loop iteration.
204 if (this->reactor ()->schedule_wakeup (handle
,
205 ACE_Event_Handler::READ_MASK
) == -1)
209 ACE_ERROR ((LM_ERROR
,
210 ACE_TEXT ("Wakeup scheduling failed\n")));
213 return this->handle_input_result ();
217 Bad_Handler::handle_close (ACE_HANDLE
,
220 if (this->handle_close_called_
)
224 ACE_ERROR_RETURN ((LM_ERROR
,
225 ACE_TEXT ("Bad_Handler::handle_close() called ")
226 ACE_TEXT ("more than once\n")),
230 this->handle_close_called_
= true;
236 Bad_Handler::handle_input_result () const
239 (this->suspension_test_
241 // Attempt to force reactor to resume the handle after the
245 // Attempt to force the new event handler to be removed from the
250 // ------------------------------------------------------------
252 register_handler (ACE_Reactor
* reactor
,
253 ACE_HANDLE read_handle
,
254 bool & okay_to_close
,
255 bool suspension_test
)
257 ACE_Event_Handler_var
bad_handler (new Bad_Handler (reactor
,
262 // Register for read events.
263 if (reactor
->register_handler (bad_handler
.handler (),
264 ACE_Event_Handler::READ_MASK
) != 0)
266 ACE_ERROR_RETURN ((LM_ERROR
,
267 ACE_TEXT ("Unable to register Bad_Handler with ")
268 ACE_TEXT ("reactor\n")),
275 // ------------------------------------------------------------
278 send_data (ACE_HANDLE write_handle
)
280 char const foo
[] = "foo";
281 size_t const len
= sizeof (foo
); // We want the number of bytes, not
282 // the number of characters.
284 ACE_Time_Value
const timeout (2);
286 // Trigger a read event on the pipe handle. This shouldn't timeout
287 // since the pipe should be able to hold such a small amount of
289 size_t bytes_transferred
= 0;
290 ssize_t
const result
=
291 ACE::send_n (write_handle
,
298 || bytes_transferred
!= len
)
300 ACE_ERROR_RETURN ((LM_ERROR
,
302 ACE_TEXT ("Unable to send data")),
309 // ------------------------------------------------------------
312 handle_events (ACE_Reactor
& reactor
,
313 bool & okay_to_close
)
315 ACE_Time_Value
timeout (2);
317 // Only one event handler should have been dispatched.
318 if (reactor
.handle_events (&timeout
) != 1)
320 ACE_ERROR ((LM_ERROR
,
321 ACE_TEXT ("Initial event dispatch failed\n")));
325 okay_to_close
= true;
327 // Run the event loop again in an attempt to make the reactor
328 // dispatch the newly registered event handler. No events
329 // should be dispatched.
331 int const result
= reactor
.handle_events (&timeout
);
336 ACE_ERROR ((LM_ERROR
,
337 ACE_TEXT ("Unexpectedly dispatched an event\n")));
343 ACE_ERROR ((LM_ERROR
,
344 ACE_TEXT ("Event loop failed unexpectedly\n")));
353 // ------------------------------------------------------------
355 using reactor_factory_type
= std::unique_ptr
<ACE_Reactor_Impl
> (*)();
357 std::unique_ptr
<ACE_Reactor_Impl
>
358 tp_reactor_factory ()
361 ACE_TEXT ("Creating ACE_TP_Reactor.\n")));
363 return std::unique_ptr
<ACE_Reactor_Impl
> (new ACE_TP_Reactor
);
366 // ------------------------------------------------------------
370 * @brief Reactor test execution functor.
372 * Reactor test execution functor.
376 typedef reactor_factory_type argument_type
;
377 typedef void result_type
;
379 /// Function call operator overload.
380 void operator() (reactor_factory_type factory
)
382 bool const suspension_test
[] =
384 true, // Run suspension test.
385 false // Run removal test.
388 bool const * const begin
= suspension_test
;
389 bool const * const end
=
391 + sizeof (suspension_test
) / sizeof (suspension_test
[0]);
393 for (bool const * i
= begin
; i
!= end
; ++i
)
395 bool const suspension_test
= *i
;
400 ACE_TEXT ("** Running suspension test **\n")));
405 ACE_TEXT ("** Running removal test **\n")));
408 std::unique_ptr
<ACE_Reactor_Impl
> the_factory (factory ());
409 ACE_Reactor
reactor (the_factory
.get ());
411 // In this test, it's only okay to close the Bogus_Handler
412 // when the reactor is destroyed.
413 bool okay_to_close
= false;
416 if (the_pipe
.open () != 0
417 || register_handler (&reactor
,
418 the_pipe
.read_handle (),
420 suspension_test
) != 0
421 || send_data (the_pipe
.write_handle ()) != 0
422 || handle_events (reactor
, okay_to_close
) != 0)
427 okay_to_close
= true;
429 ACE_DEBUG ((LM_INFO
, ACE_TEXT ("\n"))); // For log aesthetics.
434 // ------------------------------------------------------------
437 run_main (int, ACE_TCHAR
*[])
439 ACE_START_TEST (ACE_TEXT ("Reactor_Remove_Resume_Test"));
441 static reactor_factory_type
const factories
[] =
446 static size_t const factory_count
= sizeof (factories
) / sizeof (factories
[0]);
448 std::for_each (factories
, factories
+ factory_count
, Run_Test ());
450 if (overall_result
!= 0)
451 ACE_ERROR ((LM_ERROR
,
452 ACE_TEXT ("Test failed.\n")));
455 ACE_TEXT ("Test passed.\n")));
457 ACE_Event_Handler_var nullvar
;
460 ACE_DEBUG ((LM_DEBUG
,
461 ACE_TEXT ("EH_var explicit operator bool ok\n")));
465 ACE_ERROR ((LM_ERROR
,
466 ACE_TEXT ("EH_var explicit operator bool FAILED\n")));
469 if (nullvar
== nullptr)
471 ACE_DEBUG ((LM_DEBUG
,
472 ACE_TEXT ("EH_var explicit operator== nullptr ok\n")));
476 ACE_ERROR ((LM_ERROR
,
477 ACE_TEXT ("EH_var explicit operator== nullptr FAILED\n")));
480 if (!(nullvar
!= nullptr))
482 ACE_DEBUG ((LM_DEBUG
,
483 ACE_TEXT ("EH_var explicit operator!= nullptr ok\n")));
487 ACE_ERROR ((LM_ERROR
,
488 ACE_TEXT ("EH_var explicit operator!= nullptr FAILED\n")));
494 return overall_result
;