Merge pull request #2301 from sonndinh/remove-dup-reactor-functions
[ACE_TAO.git] / ACE / tests / Bug_2653_Regression_Test.cpp
blobe6e971506b55a442c42a370117792fcc73aff250
2 //=============================================================================
3 /**
4 * @file Bug_2653_Regression_Test.cpp
6 * This bug occurs when schedule_wakeup is called for a handle that does
7 * not already have an event handler registered. This can happen quite
8 * legitimately in multithreaded applications where one thread schedules
9 * the wakeup while another thread is handling the closure of the
10 * connection and unregistering.
12 * @author Phil Mesnier <mesnier_p@ociweb.com>
14 //=============================================================================
17 #include "test_config.h"
18 #include "ace/OS_NS_string.h"
19 #include "ace/Reactor.h"
20 #include "ace/TP_Reactor.h"
21 #include "ace/Pipe.h"
22 #include "ace/ACE.h"
23 #include "ace/Task.h"
24 #include "ace/OS_NS_unistd.h"
27 static const char *message =
28 "Hello there! Hope you get this message";
30 class Watchdog : public ACE_Task_Base
32 public:
33 int svc () override;
34 int my_grp_;
37 int
38 Watchdog::svc ()
40 ACE_OS::sleep (5);
41 // If we make it through the sleep and haven't been canceled, that
42 // means the process is hung.
43 if (!this->thr_mgr ()->testcancel (ACE_Thread::self ()))
44 ACE_ERROR ((LM_ERROR,
45 ACE_TEXT ("Watchdog slept without cancel - we're hung\n")));
46 return 0;
49 class Handler : public ACE_Event_Handler
51 public:
52 Handler (ACE_Reactor &reactor, bool close_other);
54 ~Handler() override;
56 int handle_input (ACE_HANDLE fd) override;
58 int handle_output (ACE_HANDLE fd) override;
60 ACE_Pipe pipe_;
61 ACE_Pipe other_pipe_;
64 Handler::Handler (ACE_Reactor &reactor, bool close_other)
65 : ACE_Event_Handler (&reactor)
67 // Create the pipe.
68 if (0 != this->other_pipe_.open () || 0 != this->pipe_.open())
70 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("pipe")));
72 else
74 // Register for all events.
75 if (0 != this->reactor ()->register_handler
76 (this->pipe_.read_handle (),
77 this,
78 ACE_Event_Handler::READ_MASK))
80 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("register")));
83 if (-1 == this->reactor ()->schedule_wakeup
84 (this->other_pipe_.write_handle(),
85 ACE_Event_Handler::WRITE_MASK))
87 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("Schedule")));
90 // closing the other pipe sets up the spinner error.
91 // leaving it open sets up the segv.
92 if (close_other)
93 this->other_pipe_.close();
97 Handler::~Handler ()
99 this->other_pipe_.close();
100 this->pipe_.close ();
104 Handler::handle_output (ACE_HANDLE)
106 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Handler::handle_output\n")));
108 #if defined (__OpenBSD__) || defined (ACE_VXWORKS)
109 // All that we need written has been written, so don't
110 // call handle_output again.
111 this->reactor ()->mask_ops (this->pipe_.read_handle (),
112 ACE_Event_Handler::WRITE_MASK,
113 ACE_Reactor::CLR_MASK);
114 #endif /* __OpenBSD__ || ACE_VXWORKS */
116 return 0;
120 Handler::handle_input (ACE_HANDLE fd)
122 char buffer[BUFSIZ];
123 ssize_t result = ACE::recv (fd, buffer, sizeof buffer);
125 if (result != ssize_t (ACE_OS::strlen (message)))
126 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Handler recv'd %b bytes; expected %B\n"),
127 result, ACE_OS::strlen (message)));
128 buffer[result] = '\0';
130 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Handler::handle_input: %C\n"), buffer));
132 if (ACE_OS::strcmp (buffer, message) != 0)
133 ACE_ERROR ((LM_ERROR,
134 ACE_TEXT ("Handler text mismatch; received \"%C\"; ")
135 ACE_TEXT ("expected \"%C\"\n"),
136 buffer, message));
138 this->reactor ()->end_reactor_event_loop ();
139 return 0;
142 static void
143 test_for_crash (ACE_Reactor &reactor)
145 Handler handler (reactor, false);
147 // This should trigger a call to <handle_input>.
148 ssize_t result =
149 ACE::send_n (handler.pipe_.write_handle (),
150 message,
151 ACE_OS::strlen (message));
152 if (result != ssize_t (ACE_OS::strlen (message)))
153 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Handler sent %b bytes; should be %B\n"),
154 result, ACE_OS::strlen (message)));
156 reactor.run_reactor_event_loop ();
158 if (0 != reactor.remove_handler (handler.pipe_.read_handle (),
159 ACE_Event_Handler::ALL_EVENTS_MASK |
160 ACE_Event_Handler::DONT_CALL))
161 ACE_ERROR ((LM_ERROR,
162 ACE_TEXT ("%p\n"),
163 ACE_TEXT ("test_for_handler, remove pipe")));
165 if (0 == reactor.remove_handler (handler.other_pipe_.write_handle (),
166 ACE_Event_Handler::ALL_EVENTS_MASK |
167 ACE_Event_Handler::DONT_CALL))
168 ACE_ERROR ((LM_ERROR,
169 ACE_TEXT ("test_for_crash remove other_pipe succeeded ")
170 ACE_TEXT ("but shouldn't\n")));
173 static void
174 test_for_spin (ACE_Reactor &reactor)
176 Handler handler (reactor, true);
178 // This should trigger a call to <handle_input>.
179 ssize_t result =
180 ACE::send_n (handler.pipe_.write_handle (),
181 message,
182 ACE_OS::strlen (message));
183 if (result != ssize_t (ACE_OS::strlen (message)))
184 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Handler sent %b bytes; should be %B\n"),
185 result, ACE_OS::strlen (message)));
187 reactor.run_reactor_event_loop ();
189 if (0 != reactor.remove_handler (handler.pipe_.read_handle (),
190 ACE_Event_Handler::ALL_EVENTS_MASK |
191 ACE_Event_Handler::DONT_CALL))
192 ACE_ERROR ((LM_ERROR,
193 ACE_TEXT ("%p\n"),
194 ACE_TEXT ("test_for_spin, remove pipe")));
196 if (0 == reactor.remove_handler (handler.other_pipe_.write_handle (),
197 ACE_Event_Handler::ALL_EVENTS_MASK |
198 ACE_Event_Handler::DONT_CALL))
199 ACE_ERROR ((LM_ERROR,
200 ACE_TEXT ("test_for_spin remove other_pipe succeeded ")
201 ACE_TEXT ("but shouldn't\n")));
205 run_main (int, ACE_TCHAR *[])
207 ACE_START_TEST (ACE_TEXT ("Bug_2653_Regression_Test"));
209 ACE_TP_Reactor tp_reactor_impl;
210 ACE_Reactor tp_reactor (&tp_reactor_impl);
211 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Testing for crash\n")));
212 test_for_crash (tp_reactor);
213 // if that passes, start the watchdog. We don't need to wait
214 Watchdog wd;
215 wd.activate ();
216 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Testing for spin\n")));
217 test_for_spin(tp_reactor);
218 // If test_for_spin returns, all is well.
219 wd.thr_mgr ()->cancel_grp (wd.grp_id ());
220 wd.wait ();
222 ACE_END_TEST;
223 return 0;