2 //=============================================================================
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"
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
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 ()))
45 ACE_TEXT ("Watchdog slept without cancel - we're hung\n")));
49 class Handler
: public ACE_Event_Handler
52 Handler (ACE_Reactor
&reactor
, bool close_other
);
56 int handle_input (ACE_HANDLE fd
) override
;
58 int handle_output (ACE_HANDLE fd
) override
;
64 Handler::Handler (ACE_Reactor
&reactor
, bool close_other
)
65 : ACE_Event_Handler (&reactor
)
68 if (0 != this->other_pipe_
.open () || 0 != this->pipe_
.open())
70 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("%p\n"), ACE_TEXT ("pipe")));
74 // Register for all events.
75 if (0 != this->reactor ()->register_handler
76 (this->pipe_
.read_handle (),
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.
93 this->other_pipe_
.close();
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 */
120 Handler::handle_input (ACE_HANDLE fd
)
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"),
138 this->reactor ()->end_reactor_event_loop ();
143 test_for_crash (ACE_Reactor
&reactor
)
145 Handler
handler (reactor
, false);
147 // This should trigger a call to <handle_input>.
149 ACE::send_n (handler
.pipe_
.write_handle (),
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
,
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")));
174 test_for_spin (ACE_Reactor
&reactor
)
176 Handler
handler (reactor
, true);
178 // This should trigger a call to <handle_input>.
180 ACE::send_n (handler
.pipe_
.write_handle (),
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
,
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
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 ());