2 * @file Bug_1890_Regression_Test.cpp
4 * Reproduces the problems reported in bug 1890
5 * http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=1890
7 * @author Carlos O'Ryan <coryan@atdesk.com>
8 * Based on a test provided by "Vadim" (no further details available)
11 #include "test_config.h"
14 #include "ace/Event_Handler.h"
15 #include "ace/Reactor.h"
16 #include "ace/Select_Reactor.h"
19 int const nhandlers
= 3;
22 * This class is used to create real I/O in the test. To keep the I/O under
23 * control and keep the test to a single process we use ACE_Pipe. This class
24 * is known to work with the Reactor, in fact, that is its main function.
26 * Handler counts how many calls to handle_input() has the reactor performed.
27 * When bug 1890 is triggered the Reactor continues to call the timers, but it
28 * stops calling select() and the handle_input() functions.
30 class Handler
: public ACE_Event_Handler
35 //FUZZ: disable check_for_lack_ACE_OS
36 /// Initialize the pipe and register with the reactor
37 int open(ACE_Reactor
* reactor
);
38 //FUZZ: enable check_for_lack_ACE_OS
40 /// Return the current count
41 size_t handle_input_count() const;
44 void send_dummy_data();
47 ACE_HANDLE
get_handle() const override
;
48 int handle_input(ACE_HANDLE
) override
;
51 size_t handle_input_count_
;
55 ACE_HANDLE handles_
[2];
59 * This is the main driver for the test. This timer is called by the reactor
60 * in a repeating interval. On the first @c initial_iterations the Timer
61 * writes data through all of its handlers. On iteration @c initial_iteration
62 * it triggers bug 1890 by removing all the handlers from the reactor, and
63 * then re-adding one handler.
65 class Timer
: public ACE_Event_Handler
70 //FUZZ: disable check_for_lack_ACE_OS
71 int open(ACE_Reactor
* reactor
);
73 //FUZZ: enable check_for_lack_ACE_OS
75 bool check_expected_results() const;
77 int handle_timeout(ACE_Time_Value
const &, void const*) override
;
80 void send_data_through_handlers();
81 void remove_some_handlers();
83 Handler
& special_handler();
84 Handler
const & special_handler() const;
87 Handler handler_
[nhandlers
];
90 size_t recorded_count_
;
94 run_main (int, ACE_TCHAR
*[])
96 ACE_START_TEST (ACE_TEXT ("Bug_1890_Regression_Test"));
100 // Bug 1890 is all about ACE_Select_Reactor, so run it on that reactor
101 // regardless of platform.
102 ACE_Select_Reactor
*impl_ptr
= 0;
103 ACE_NEW_RETURN (impl_ptr
, ACE_Select_Reactor
, -1);
104 std::unique_ptr
<ACE_Select_Reactor
> auto_impl (impl_ptr
);
106 ACE_Reactor
reactor (impl_ptr
);
108 // Create the timer, this is the main driver for the test
109 Timer
* timer
= new Timer
;
111 // Initialize the timer and register with the reactor
112 if (-1 == timer
->open (&reactor
))
114 ACE_ERROR_RETURN ((LM_ERROR
,
116 ACE_TEXT ("Cannot initialize timer")),
120 reactor
.run_reactor_event_loop ();
122 // Verify that the results are what we expect
123 if (!(success
= timer
->check_expected_results ()))
124 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("Test failed\n")));
132 return success
? 0 : -1;
136 : handle_input_count_(0)
142 Handler::open (ACE_Reactor
* r
)
144 if (-1 == the_pipe_
.open (handles_
))
148 if (-1 == r
->register_handler (this, ACE_Event_Handler::READ_MASK
))
156 Handler::handle_input_count() const
158 return handle_input_count_
;
162 Handler::send_dummy_data()
164 char buf
[] = "dummy";
165 (void) the_pipe_
.send (buf
, sizeof (buf
));
169 Handler::get_handle() const
171 return the_pipe_
.read_handle ();
175 Handler::handle_input(ACE_HANDLE
)
177 ++handle_input_count_
;
178 // ACE_DEBUG((LM_DEBUG, "Handler::handle_input called for %d\n", h));
182 int const initial_iterations
= 5;
183 int const total_iterations
= 10;
185 int const special_handler_index
= nhandlers
- 1;
194 Timer::open (ACE_Reactor
* r
)
198 // Initialize both handles and register them with the reactor for reading.
199 for (int i
= 0; i
!= nhandlers
; ++i
)
201 if (-1 == handler_
[i
].open (r
))
203 ACE_ERROR_RETURN ((LM_ERROR
,
204 ACE_TEXT ("Could not open dummy handler %d %p\n"),
211 ACE_Time_Value
const interval(0, ACE_ONE_SECOND_IN_USECS
/ 10);
212 ACE_Time_Value
const startup (0, ACE_ONE_SECOND_IN_USECS
/ 20);
214 if (-1 == r
->schedule_timer (this, 0, startup
, interval
))
216 ACE_ERROR_RETURN ((LM_ERROR
,
218 ACE_TEXT ("Could not schedule timer")),
228 for (int i
= 0; i
!= nhandlers
; ++i
)
230 this->reactor ()->remove_handler (&handler_
[i
],
231 ACE_Event_Handler::ALL_EVENTS_MASK
|
232 ACE_Event_Handler::DONT_CALL
);
234 this->reactor ()->cancel_timer (this);
238 Timer::check_expected_results() const
240 if (this->recorded_count_
< this->special_handler ().handle_input_count ())
244 ACE_ERROR ((LM_ERROR
,
245 ACE_TEXT ("recorded_count %B, special_handler count %B\n"),
246 this->recorded_count_
,
247 this->special_handler ().handle_input_count ()));
252 Timer::handle_timeout(ACE_Time_Value
const &, void const *)
256 send_data_through_handlers();
260 if (iteration_
< initial_iterations
)
265 if (iteration_
== initial_iterations
)
267 remove_some_handlers();
268 recorded_count_
= special_handler().handle_input_count();
272 if (iteration_
< total_iterations
)
277 reactor()->end_reactor_event_loop();
283 Timer::send_data_through_handlers()
285 for (int i
= 0; i
!= nhandlers
; ++i
)
287 handler_
[i
].send_dummy_data();
292 Timer::remove_some_handlers()
294 // The reactor may not get around to callbacks on deletion until the test
296 ACE_Reactor_Mask mask
=
297 ACE_Event_Handler::ALL_EVENTS_MASK
| ACE_Event_Handler::DONT_CALL
;
298 for (int i
= 0; i
!= nhandlers
; ++i
)
300 if (-1 == reactor()->remove_handler(&handler_
[i
], mask
))
302 ACE_ERROR ((LM_ERROR
,
303 ACE_TEXT ("Cannot remove handler %d in %p\n"),
305 ACE_TEXT ("timeout")));
309 if (-1 == reactor()->register_handler(&special_handler(),
310 ACE_Event_Handler::ALL_EVENTS_MASK
))
312 ACE_ERROR ((LM_ERROR
,
313 ACE_TEXT ("Cannot add back special handler in %p\n"),
314 ACE_TEXT ("timeout")));
318 Handler
& Timer::special_handler()
320 return handler_
[special_handler_index
];
323 Handler
const & Timer::special_handler() const
325 return handler_
[special_handler_index
];