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"
28 static const char *message
=
29 "Hello there! Hope you get this message";
31 class Watchdog
: public ACE_Task_Base
42 // If we make it through the sleep and haven't been canceled, that
43 // means the process is hung.
44 if (!this->thr_mgr ()->testcancel (ACE_Thread::self ()))
46 ACE_TEXT ("Watchdog slept without cancel - we're hung\n")));
50 class Handler
: public ACE_Event_Handler
53 Handler (ACE_Reactor
&reactor
, bool close_other
);
57 int handle_input (ACE_HANDLE fd
);
59 int handle_output (ACE_HANDLE fd
);
65 Handler::Handler (ACE_Reactor
&reactor
, bool close_other
)
66 : ACE_Event_Handler (&reactor
)
69 if (0 != this->other_pipe_
.open () || 0 != this->pipe_
.open())
71 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("%p\n"), ACE_TEXT ("pipe")));
75 // Register for all events.
76 if (0 != this->reactor ()->register_handler
77 (this->pipe_
.read_handle (),
79 ACE_Event_Handler::READ_MASK
))
81 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("%p\n"), ACE_TEXT ("register")));
84 if (-1 == this->reactor ()->schedule_wakeup
85 (this->other_pipe_
.write_handle(),
86 ACE_Event_Handler::WRITE_MASK
))
88 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("%p\n"), ACE_TEXT ("Schedule")));
91 // closing the other pipe sets up the spinner error.
92 // leaving it open sets up the segv.
94 this->other_pipe_
.close();
98 Handler::~Handler (void)
100 this->other_pipe_
.close();
101 this->pipe_
.close ();
105 Handler::handle_output (ACE_HANDLE
)
107 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Handler::handle_output\n")));
109 #if defined (__OpenBSD__) || defined (ACE_VXWORKS)
110 // All that we need written has been written, so don't
111 // call handle_output again.
112 this->reactor ()->mask_ops (this->pipe_
.read_handle (),
113 ACE_Event_Handler::WRITE_MASK
,
114 ACE_Reactor::CLR_MASK
);
115 #endif /* __OpenBSD__ || ACE_VXWORKS */
121 Handler::handle_input (ACE_HANDLE fd
)
124 ssize_t result
= ACE::recv (fd
, buffer
, sizeof buffer
);
126 if (result
!= ssize_t (ACE_OS::strlen (message
)))
127 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("Handler recv'd %b bytes; expected %B\n"),
128 result
, ACE_OS::strlen (message
)));
129 buffer
[result
] = '\0';
131 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Handler::handle_input: %C\n"), buffer
));
133 if (ACE_OS::strcmp (buffer
, message
) != 0)
134 ACE_ERROR ((LM_ERROR
,
135 ACE_TEXT ("Handler text mismatch; received \"%C\"; ")
136 ACE_TEXT ("expected \"%C\"\n"),
139 this->reactor ()->end_reactor_event_loop ();
144 test_for_crash (ACE_Reactor
&reactor
)
146 Handler
handler (reactor
, false);
148 // This should trigger a call to <handle_input>.
150 ACE::send_n (handler
.pipe_
.write_handle (),
152 ACE_OS::strlen (message
));
153 if (result
!= ssize_t (ACE_OS::strlen (message
)))
154 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("Handler sent %b bytes; should be %B\n"),
155 result
, ACE_OS::strlen (message
)));
157 reactor
.run_reactor_event_loop ();
159 if (0 != reactor
.remove_handler (handler
.pipe_
.read_handle (),
160 ACE_Event_Handler::ALL_EVENTS_MASK
|
161 ACE_Event_Handler::DONT_CALL
))
162 ACE_ERROR ((LM_ERROR
,
164 ACE_TEXT ("test_for_handler, remove pipe")));
166 if (0 == reactor
.remove_handler (handler
.other_pipe_
.write_handle (),
167 ACE_Event_Handler::ALL_EVENTS_MASK
|
168 ACE_Event_Handler::DONT_CALL
))
169 ACE_ERROR ((LM_ERROR
,
170 ACE_TEXT ("test_for_crash remove other_pipe succeeded ")
171 ACE_TEXT ("but shouldn't\n")));
175 test_for_spin (ACE_Reactor
&reactor
)
177 Handler
handler (reactor
, true);
179 // This should trigger a call to <handle_input>.
181 ACE::send_n (handler
.pipe_
.write_handle (),
183 ACE_OS::strlen (message
));
184 if (result
!= ssize_t (ACE_OS::strlen (message
)))
185 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("Handler sent %b bytes; should be %B\n"),
186 result
, ACE_OS::strlen (message
)));
188 reactor
.run_reactor_event_loop ();
190 if (0 != reactor
.remove_handler (handler
.pipe_
.read_handle (),
191 ACE_Event_Handler::ALL_EVENTS_MASK
|
192 ACE_Event_Handler::DONT_CALL
))
193 ACE_ERROR ((LM_ERROR
,
195 ACE_TEXT ("test_for_spin, remove pipe")));
197 if (0 == reactor
.remove_handler (handler
.other_pipe_
.write_handle (),
198 ACE_Event_Handler::ALL_EVENTS_MASK
|
199 ACE_Event_Handler::DONT_CALL
))
200 ACE_ERROR ((LM_ERROR
,
201 ACE_TEXT ("test_for_spin remove other_pipe succeeded ")
202 ACE_TEXT ("but shouldn't\n")));
206 run_main (int, ACE_TCHAR
*[])
208 ACE_START_TEST (ACE_TEXT ("Bug_2653_Regression_Test"));
210 ACE_TP_Reactor tp_reactor_impl
;
211 ACE_Reactor
tp_reactor (&tp_reactor_impl
);
212 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Testing for crash\n")));
213 test_for_crash (tp_reactor
);
214 // if that passes, start the watchdog. We don't need to wait
217 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Testing for spin\n")));
218 test_for_spin(tp_reactor
);
219 // If test_for_spin returns, all is well.
220 wd
.thr_mgr ()->cancel_grp (wd
.grp_id ());