Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / tests / Reactor_Remove_Resume_Test.cpp
blobd0b4fd40bacca1452bc9f2d9f6578540ac0dc8dd
1 /**
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"
19 #include "ace/Pipe.h"
20 #include <memory>
22 #include <algorithm>
23 #include <functional>
25 int overall_result = 0;
27 // ------------------------------------------------------------
29 class Bogus_Handler : public ACE_Event_Handler
31 public:
32 Bogus_Handler (ACE_Reactor * reactor,
33 ACE_HANDLE read_handle,
34 bool & okay_to_close);
36 protected:
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;
45 private:
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,
55 bool & okay_to_close)
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 ()
68 ACE_HANDLE
69 Bogus_Handler::get_handle () const
71 return this->read_handle_;
74 int
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")),
82 -1);
85 int
86 Bogus_Handler::handle_close (ACE_HANDLE,
87 ACE_Reactor_Mask)
89 if (this->okay_to_close_)
90 return 0;
92 overall_result = -1;
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")),
97 -1);
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
111 public:
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;
119 protected:
120 ~Bad_Handler () override;
122 private:
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;
130 private:
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 ()
161 ACE_HANDLE
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)
175 overall_result = -1;
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 (),
185 handle,
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)
194 overall_result = -1;
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)
207 overall_result = -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,
218 ACE_Reactor_Mask)
220 if (this->handle_close_called_)
222 overall_result = -1;
224 ACE_ERROR_RETURN ((LM_ERROR,
225 ACE_TEXT ("Bad_Handler::handle_close() called ")
226 ACE_TEXT ("more than once\n")),
227 -1);
230 this->handle_close_called_ = true;
232 return 0;
236 Bad_Handler::handle_input_result () const
238 return
239 (this->suspension_test_
241 // Attempt to force reactor to resume the handle after the
242 // upcall completes.
245 // Attempt to force the new event handler to be removed from the
246 // reactor.
247 : -1);
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,
258 read_handle,
259 okay_to_close,
260 suspension_test));
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")),
269 -1);
272 return 0;
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
288 // data.
289 size_t bytes_transferred = 0;
290 ssize_t const result =
291 ACE::send_n (write_handle,
292 foo,
293 len,
294 &timeout, // timeout
295 &bytes_transferred);
297 if (result == -1
298 || bytes_transferred != len)
300 ACE_ERROR_RETURN ((LM_ERROR,
301 ACE_TEXT ("%p\n"),
302 ACE_TEXT ("Unable to send data")),
303 -1);
306 return 0;
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")));
323 else
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.
330 timeout.sec (2);
331 int const result = reactor.handle_events (&timeout);
334 if (result > 0)
336 ACE_ERROR ((LM_ERROR,
337 ACE_TEXT ("Unexpectedly dispatched an event\n")));
339 else if (result < 0)
341 overall_result = -1;
343 ACE_ERROR ((LM_ERROR,
344 ACE_TEXT ("Event loop failed unexpectedly\n")));
346 else
347 return 0;
350 return -1;
353 // ------------------------------------------------------------
355 using reactor_factory_type = std::unique_ptr<ACE_Reactor_Impl> (*)();
357 std::unique_ptr<ACE_Reactor_Impl>
358 tp_reactor_factory ()
360 ACE_DEBUG ((LM_INFO,
361 ACE_TEXT ("Creating ACE_TP_Reactor.\n")));
363 return std::unique_ptr<ACE_Reactor_Impl> (new ACE_TP_Reactor);
366 // ------------------------------------------------------------
368 * @struct Caller
370 * @brief Reactor test execution functor.
372 * Reactor test execution functor.
374 struct Run_Test
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 =
390 suspension_test
391 + sizeof (suspension_test) / sizeof (suspension_test[0]);
393 for (bool const * i = begin; i != end; ++i)
395 bool const suspension_test = *i;
397 if (suspension_test)
399 ACE_DEBUG ((LM_INFO,
400 ACE_TEXT ("** Running suspension test **\n")));
402 else
404 ACE_DEBUG ((LM_INFO,
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;
415 ACE_Pipe the_pipe;
416 if (the_pipe.open () != 0
417 || register_handler (&reactor,
418 the_pipe.read_handle (),
419 okay_to_close,
420 suspension_test) != 0
421 || send_data (the_pipe.write_handle ()) != 0
422 || handle_events (reactor, okay_to_close) != 0)
424 overall_result = -1;
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[] =
443 tp_reactor_factory
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")));
453 else
454 ACE_ERROR ((LM_INFO,
455 ACE_TEXT ("Test passed.\n")));
457 ACE_Event_Handler_var nullvar;
458 if (!nullvar)
460 ACE_DEBUG ((LM_DEBUG,
461 ACE_TEXT ("EH_var explicit operator bool ok\n")));
463 else
465 ACE_ERROR ((LM_ERROR,
466 ACE_TEXT ("EH_var explicit operator bool FAILED\n")));
467 ++overall_result;
469 if (nullvar == nullptr)
471 ACE_DEBUG ((LM_DEBUG,
472 ACE_TEXT ("EH_var explicit operator== nullptr ok\n")));
474 else
476 ACE_ERROR ((LM_ERROR,
477 ACE_TEXT ("EH_var explicit operator== nullptr FAILED\n")));
478 ++overall_result;
480 if (!(nullvar != nullptr))
482 ACE_DEBUG ((LM_DEBUG,
483 ACE_TEXT ("EH_var explicit operator!= nullptr ok\n")));
485 else
487 ACE_ERROR ((LM_ERROR,
488 ACE_TEXT ("EH_var explicit operator!= nullptr FAILED\n")));
489 ++overall_result;
492 ACE_END_TEST;
494 return overall_result;