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"
29 int overall_result
= 0;
31 // ------------------------------------------------------------
33 class Bogus_Handler
: public ACE_Event_Handler
36 Bogus_Handler (ACE_Reactor
* reactor
,
37 ACE_HANDLE read_handle
,
38 bool & okay_to_close
);
41 ~Bogus_Handler () override
;
43 ACE_HANDLE
get_handle () const override
;
44 int handle_input (ACE_HANDLE handle
) override
;
45 int handle_close (ACE_HANDLE handle
,
46 ACE_Reactor_Mask close_mask
) override
;
47 int resume_handler () override
;
50 ACE_HANDLE
const read_handle_
;
52 // If the reactor closes the event handler before it gets the okay,
53 // we will issue an error.
54 bool & okay_to_close_
;
57 Bogus_Handler::Bogus_Handler (ACE_Reactor
* reactor
,
58 ACE_HANDLE read_handle
,
60 : ACE_Event_Handler (reactor
)
61 , read_handle_ (read_handle
)
62 , okay_to_close_ (okay_to_close
)
64 this->reference_counting_policy ().value (
65 ACE_Event_Handler::Reference_Counting_Policy::ENABLED
);
68 Bogus_Handler::~Bogus_Handler ()
73 Bogus_Handler::get_handle () const
75 return this->read_handle_
;
79 Bogus_Handler::handle_input (ACE_HANDLE
)
81 // This event handler should have been suspended, meaning it should
82 // not have received any events.
83 ACE_ERROR_RETURN ((LM_ERROR
,
84 ACE_TEXT ("Bogus_Handler received an ")
85 ACE_TEXT ("unexpected event.\n")),
90 Bogus_Handler::handle_close (ACE_HANDLE
,
93 if (this->okay_to_close_
)
98 // This event handler is being closed by the reactor unexpectedly.
99 ACE_ERROR_RETURN ((LM_ERROR
,
100 ACE_TEXT ("Bogus_Handler unexpectedly closed\n")),
105 Bogus_Handler::resume_handler ()
107 // We don't want the reactor to resume this event handler.
108 return ACE_APPLICATION_RESUMES_HANDLER
;
111 // ------------------------------------------------------------
113 class Bad_Handler
: public ACE_Event_Handler
116 Bad_Handler (ACE_Reactor
* reactor
,
117 ACE_HANDLE read_handle
,
118 bool & okay_to_close
,
119 bool suspension_test
);
121 ACE_HANDLE
write_handle () const;
124 ~Bad_Handler () override
;
127 ACE_HANDLE
get_handle () const override
;
128 int handle_input (ACE_HANDLE handle
) override
;
129 int handle_close (ACE_HANDLE handle
,
130 ACE_Reactor_Mask close_mask
) override
;
132 int handle_input_result () const;
135 ACE_HANDLE
const read_handle_
;
137 bool handle_close_called_
;
139 // Passed on to the Bogus_Handler constructor. Not used by the
140 // Bad_Handler, otherwise.
141 bool & okay_to_close_
;
143 // Are we running the event handler suspension or removal test?
144 bool suspension_test_
;
147 Bad_Handler::Bad_Handler (ACE_Reactor
* reactor
,
148 ACE_HANDLE read_handle
,
149 bool & okay_to_close
,
150 bool suspension_test
)
151 : ACE_Event_Handler (reactor
)
152 , read_handle_ (read_handle
)
153 , handle_close_called_ (false)
154 , okay_to_close_ (okay_to_close
)
155 , suspension_test_ (suspension_test
)
157 this->reference_counting_policy ().value (
158 ACE_Event_Handler::Reference_Counting_Policy::ENABLED
);
161 Bad_Handler::~Bad_Handler ()
166 Bad_Handler::get_handle () const
168 return this->read_handle_
;
172 Bad_Handler::handle_input (ACE_HANDLE handle
)
174 // Remove ourselves from the reactor, and trigger a different one
175 // with the same handle to be registered.
176 if (this->reactor ()->remove_handler (handle
,
177 ACE_Event_Handler::READ_MASK
) != 0)
181 ACE_ERROR_RETURN ((LM_ERROR
,
182 ACE_TEXT ("Unable to remove Bad_Handler ")
183 ACE_TEXT ("from reactor\n")),
187 ACE_Event_Handler_var
bogus_handler (
188 new Bogus_Handler (this->reactor (),
190 this->okay_to_close_
));
192 // Register and suspend a new handler.
193 if (this->reactor ()->register_handler (handle
,
194 bogus_handler
.handler (),
195 ACE_Event_Handler::READ_MASK
) != 0
196 || this->reactor ()->suspend_handler (handle
) != 0)
200 ACE_ERROR_RETURN ((LM_ERROR
,
201 ACE_TEXT ("Unable to register or suspend ")
202 ACE_TEXT ("Bogus_Handler\n")),
206 // Make sure a read event exists for dispatching during the next
207 // event loop iteration.
208 if (this->reactor ()->schedule_wakeup (handle
,
209 ACE_Event_Handler::READ_MASK
) == -1)
213 ACE_ERROR ((LM_ERROR
,
214 ACE_TEXT ("Wakeup scheduling failed\n")));
217 return this->handle_input_result ();
221 Bad_Handler::handle_close (ACE_HANDLE
,
224 if (this->handle_close_called_
)
228 ACE_ERROR_RETURN ((LM_ERROR
,
229 ACE_TEXT ("Bad_Handler::handle_close() called ")
230 ACE_TEXT ("more than once\n")),
234 this->handle_close_called_
= true;
240 Bad_Handler::handle_input_result () const
243 (this->suspension_test_
245 // Attempt to force reactor to resume the handle after the
249 // Attempt to force the new event handler to be removed from the
254 // ------------------------------------------------------------
256 register_handler (ACE_Reactor
* reactor
,
257 ACE_HANDLE read_handle
,
258 bool & okay_to_close
,
259 bool suspension_test
)
261 ACE_Event_Handler_var
bad_handler (new Bad_Handler (reactor
,
266 // Register for read events.
267 if (reactor
->register_handler (bad_handler
.handler (),
268 ACE_Event_Handler::READ_MASK
) != 0)
270 ACE_ERROR_RETURN ((LM_ERROR
,
271 ACE_TEXT ("Unable to register Bad_Handler with ")
272 ACE_TEXT ("reactor\n")),
279 // ------------------------------------------------------------
282 send_data (ACE_HANDLE write_handle
)
284 char const foo
[] = "foo";
285 size_t const len
= sizeof (foo
); // We want the number of bytes, not
286 // the number of characters.
288 ACE_Time_Value
const timeout (2);
290 // Trigger a read event on the pipe handle. This shouldn't timeout
291 // since the pipe should be able to hold such a small amount of
293 size_t bytes_transferred
= 0;
294 ssize_t
const result
=
295 ACE::send_n (write_handle
,
302 || bytes_transferred
!= len
)
304 ACE_ERROR_RETURN ((LM_ERROR
,
306 ACE_TEXT ("Unable to send data")),
313 // ------------------------------------------------------------
316 handle_events (ACE_Reactor
& reactor
,
317 bool & okay_to_close
)
319 ACE_Time_Value
timeout (2);
321 // Only one event handler should have been dispatched.
322 if (reactor
.handle_events (&timeout
) != 1)
324 ACE_ERROR ((LM_ERROR
,
325 ACE_TEXT ("Initial event dispatch failed\n")));
329 okay_to_close
= true;
331 // Run the event loop again in an attempt to make the reactor
332 // dispatch the newly registered event handler. No events
333 // should be dispatched.
335 int const result
= reactor
.handle_events (&timeout
);
340 ACE_ERROR ((LM_ERROR
,
341 ACE_TEXT ("Unexpectedly dispatched an event\n")));
347 ACE_ERROR ((LM_ERROR
,
348 ACE_TEXT ("Event loop failed unexpectedly\n")));
357 // ------------------------------------------------------------
359 using reactor_factory_type
= std::unique_ptr
<ACE_Reactor_Impl
> (*)();
361 std::unique_ptr
<ACE_Reactor_Impl
>
362 dev_poll_reactor_factory ()
365 ACE_TEXT ("Creating ACE_Dev_Poll_Reactor.\n")));
367 return std::unique_ptr
<ACE_Reactor_Impl
> (new ACE_Dev_Poll_Reactor
);
370 // ------------------------------------------------------------
374 * @brief Reactor test execution functor.
376 * Reactor test execution functor.
378 struct Run_Test
: public std::function
<void(reactor_factory_type
)>
380 /// Function call operator overload.
381 void operator() (reactor_factory_type factory
)
383 bool const suspension_test
[] =
385 true, // Run suspension test.
386 false // Run removal test.
389 bool const * const begin
= suspension_test
;
390 bool const * const end
=
392 + sizeof (suspension_test
) / sizeof (suspension_test
[0]);
394 for (bool const * i
= begin
; i
!= end
; ++i
)
396 bool const suspension_test
= *i
;
401 ACE_TEXT ("** Running suspension test **\n")));
406 ACE_TEXT ("** Running removal test **\n")));
409 std::unique_ptr
<ACE_Reactor_Impl
> the_factory (factory ());
410 ACE_Reactor
reactor (the_factory
.get ());
412 // In this test, it's only okay to close the Bogus_Handler
413 // when the reactor is destroyed.
414 bool okay_to_close
= false;
417 if (the_pipe
.open () != 0
418 || register_handler (&reactor
,
419 the_pipe
.read_handle (),
421 suspension_test
) != 0
422 || send_data (the_pipe
.write_handle ()) != 0
423 || handle_events (reactor
, okay_to_close
) != 0)
428 okay_to_close
= true;
430 ACE_DEBUG ((LM_INFO
, ACE_TEXT ("\n"))); // For log aesthetics.
435 // ------------------------------------------------------------
438 run_main (int, ACE_TCHAR
*[])
440 ACE_START_TEST (ACE_TEXT ("Reactor_Remove_Resume_Test_Dev_Poll"));
442 static reactor_factory_type
const factories
[] =
444 dev_poll_reactor_factory
447 static size_t const factory_count
= sizeof (factories
) / sizeof (factories
[0]);
449 std::for_each (factories
, factories
+ factory_count
, Run_Test ());
451 if (overall_result
!= 0)
452 ACE_ERROR ((LM_ERROR
,
453 ACE_TEXT ("Test failed.\n")));
456 ACE_TEXT ("Test passed.\n")));
460 return overall_result
;
462 #else /* ACE_HAS_EVENT_POLL || ACE_HAS_DEV_POLL */
464 run_main (int, ACE_TCHAR
*[])
466 ACE_START_TEST (ACE_TEXT ("Reactor_Remove_Resume_Test_Dev_Poll"));
467 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_Dev_Poll_Reactor is not supported in this build\n")));
472 #endif /* ACE_HAS_EVENT_POLL || ACE_HAS_DEV_POLL */