Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / tests / Reactor_Remove_Resume_Test_Dev_Poll.cpp
blob7b593fe33eb5a10af77b1c3b542d67feb20f6436
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 <memory>
26 #include <algorithm>
27 #include <functional>
29 int overall_result = 0;
31 // ------------------------------------------------------------
33 class Bogus_Handler : public ACE_Event_Handler
35 public:
36 Bogus_Handler (ACE_Reactor * reactor,
37 ACE_HANDLE read_handle,
38 bool & okay_to_close);
40 protected:
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;
49 private:
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,
59 bool & okay_to_close)
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 ()
72 ACE_HANDLE
73 Bogus_Handler::get_handle () const
75 return this->read_handle_;
78 int
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")),
86 -1);
89 int
90 Bogus_Handler::handle_close (ACE_HANDLE,
91 ACE_Reactor_Mask)
93 if (this->okay_to_close_)
94 return 0;
96 overall_result = -1;
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")),
101 -1);
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
115 public:
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;
123 protected:
124 ~Bad_Handler () override;
126 private:
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;
134 private:
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 ()
165 ACE_HANDLE
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)
179 overall_result = -1;
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 (),
189 handle,
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)
198 overall_result = -1;
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)
211 overall_result = -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,
222 ACE_Reactor_Mask)
224 if (this->handle_close_called_)
226 overall_result = -1;
228 ACE_ERROR_RETURN ((LM_ERROR,
229 ACE_TEXT ("Bad_Handler::handle_close() called ")
230 ACE_TEXT ("more than once\n")),
231 -1);
234 this->handle_close_called_ = true;
236 return 0;
240 Bad_Handler::handle_input_result () const
242 return
243 (this->suspension_test_
245 // Attempt to force reactor to resume the handle after the
246 // upcall completes.
249 // Attempt to force the new event handler to be removed from the
250 // reactor.
251 : -1);
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,
262 read_handle,
263 okay_to_close,
264 suspension_test));
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")),
273 -1);
276 return 0;
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
292 // data.
293 size_t bytes_transferred = 0;
294 ssize_t const result =
295 ACE::send_n (write_handle,
296 foo,
297 len,
298 &timeout, // timeout
299 &bytes_transferred);
301 if (result == -1
302 || bytes_transferred != len)
304 ACE_ERROR_RETURN ((LM_ERROR,
305 ACE_TEXT ("%p\n"),
306 ACE_TEXT ("Unable to send data")),
307 -1);
310 return 0;
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")));
327 else
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.
334 timeout.sec (2);
335 int const result = reactor.handle_events (&timeout);
338 if (result > 0)
340 ACE_ERROR ((LM_ERROR,
341 ACE_TEXT ("Unexpectedly dispatched an event\n")));
343 else if (result < 0)
345 overall_result = -1;
347 ACE_ERROR ((LM_ERROR,
348 ACE_TEXT ("Event loop failed unexpectedly\n")));
350 else
351 return 0;
354 return -1;
357 // ------------------------------------------------------------
359 using reactor_factory_type = std::unique_ptr<ACE_Reactor_Impl> (*)();
361 std::unique_ptr<ACE_Reactor_Impl>
362 dev_poll_reactor_factory ()
364 ACE_DEBUG ((LM_INFO,
365 ACE_TEXT ("Creating ACE_Dev_Poll_Reactor.\n")));
367 return std::unique_ptr<ACE_Reactor_Impl> (new ACE_Dev_Poll_Reactor);
370 // ------------------------------------------------------------
372 * @struct Caller
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 =
391 suspension_test
392 + sizeof (suspension_test) / sizeof (suspension_test[0]);
394 for (bool const * i = begin; i != end; ++i)
396 bool const suspension_test = *i;
398 if (suspension_test)
400 ACE_DEBUG ((LM_INFO,
401 ACE_TEXT ("** Running suspension test **\n")));
403 else
405 ACE_DEBUG ((LM_INFO,
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;
416 ACE_Pipe the_pipe;
417 if (the_pipe.open () != 0
418 || register_handler (&reactor,
419 the_pipe.read_handle (),
420 okay_to_close,
421 suspension_test) != 0
422 || send_data (the_pipe.write_handle ()) != 0
423 || handle_events (reactor, okay_to_close) != 0)
425 overall_result = -1;
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")));
454 else
455 ACE_ERROR ((LM_INFO,
456 ACE_TEXT ("Test passed.\n")));
458 ACE_END_TEST;
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")));
468 ACE_END_TEST;
470 return 0;
472 #endif /* ACE_HAS_EVENT_POLL || ACE_HAS_DEV_POLL */