Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / examples / Reactor / Misc / test_signals_2.cpp
blob437aedee1bb1f869b3146603445ec8b3a1943dc8
1 // Test the ability of the Reactor/Signal_Handler to register multiple
2 // handler per-signal.
4 /* This test works as follows:
6 1. To test the "original" semantics of ACE (i.e., only one
7 ACE_Event_Handler can be registered per signal), you don't
8 need to do anything special. Existing programs work the
9 same since giving the Reactor's constructor a 0 value
10 (which is the default argument, BTW) instructs it to behave
11 as before. When a 0 is given, the ACE_Reactor's
12 constructor/open method creates an instance of
13 ACE_Sig_Handler and assigns this to an internal pointer.
14 This pointer is then used to dispatch all signal-related
15 methods within the Reactor. The default ACE_Sig_Handler
16 only allows *one* ACE_Event_Handler to be registered
17 per-signal.
19 To run this version of the test do the following:
21 % ./test-signal
22 ./test_signals
23 waiting for SIGINT or SIGQUIT
25 signal Interrupt occurred in Sig_Handler_2 (fruity, 0, 0) with count = 1
26 waiting for SIGINT or SIGQUIT
28 signal Quit occurred in Sig_Handler_2 (fruity, 0, 0) with count = 2
29 shutting down SIGQUIT in Sig_Handler_2 (fruity, 0, 0)
30 waiting for SIGINT or SIGQUIT
32 signal Interrupt occurred in Sig_Handler_2 (fruity, 0, 0) with count = 3
33 waiting for SIGINT or SIGQUIT
34 ^\Quit (core dumped)
36 Note that in this test only one handler (the last one --
37 "Sig_Handler_2 (fruity)") is actually registered. BTW, the
38 core dump is the expected behavior since the default
39 disposition is restored when there are no more handlers
40 (see the code below).
42 2. To test the "multiple handlers per-signal semantics", you
43 need to pass the constructor/open method of the ACE_Reactor
44 a pointer to a an instance of ACE_Sig_Handlers (note the
45 plural "s"). ACE_Sig_Handlers is a class that derives from
46 ACE_Sig_Handler. The difference between these two classes
47 is that (1) ACE_Sig_Handlers::register_signal allows
48 multiple ACE_Event_Handlers to be registered per-signal and
49 (2) it enables SA_RESTART by default. This class also
50 implements Detlef Becker's algorithm for integrating ACE
51 signal handling with 3rd party libraries.
53 To run this version of the test do the following:
55 % ./test_signals 1
57 waiting for SIGINT or SIGQUIT
59 signal Interrupt occurred in external handler!
60 signal Interrupt occurred in Sig_Handler_1 (howdy, 3, 1) with count = 1
61 shutting down SIGINT in Sig_Handler_1 (howdy, 3, 1)
62 signal Interrupt occurred in Sig_Handler_1 (doody, 5, 4) with count = 1
63 shutting down SIGINT in Sig_Handler_1 (doody, 5, 4)
64 signal Interrupt occurred in Sig_Handler_2 (tutty, 7, 6) with count = 1
65 signal Interrupt occurred in Sig_Handler_2 (fruity, 9, 8) with count = 1
66 waiting for SIGINT or SIGQUIT
68 signal Quit occurred in Sig_Handler_1 (howdy, 3, 1) with count = 2
69 shutting down SIGQUIT in Sig_Handler_1 (howdy, 3, 1)
70 signal Quit occurred in Sig_Handler_1 (doody, 5, 4) with count = 2
71 shutting down SIGQUIT in Sig_Handler_1 (doody, 5, 4)
72 signal Quit occurred in Sig_Handler_2 (tutty, 7, 6) with count = 2
73 shutting down SIGQUIT in Sig_Handler_2 (tutty, 7, 6)
74 signal Quit occurred in Sig_Handler_2 (fruity, 9, 8) with count = 2
75 shutting down SIGQUIT in Sig_Handler_2 (fruity, 9, 8)
76 waiting for SIGINT or SIGQUIT
78 signal Interrupt occurred in external handler!
79 signal Interrupt occurred in Sig_Handler_2 (tutty, 7, 6) with count = 3
80 signal Interrupt occurred in Sig_Handler_2 (fruity, 9, 8) with count = 3
81 waiting for SIGINT or SIGQUIT
82 ^\Quit (core dumped)
84 When this test begins all four handlers are registered and
85 dispatched when a SIGINT or SIGQUIT occurs. After the
86 first SIGINT, the handle_signal method of the Sig_Handler_1
87 objects unregister themselves. At that point there are 4
88 SIGQUIT handlers left, but only 2 of our SIGINT handlers
89 left (and the 1 external handler). After the first
90 SIGQUIT, there are no SIGQUIT handlers left since they all
91 deregister themselves (which restores the "SIG_DFL"
92 disposition). On the second SIGINT there are only 3
93 handlers left (2 of ours and 1 external). Finally, on the
94 second SIGQUIT we exit and dump core since that's what
95 happens with the default disposition for SIGQUIT. */
98 #include "ace/Reactor.h"
99 #include "ace/WFMO_Reactor.h"
100 #include "ace/Select_Reactor.h"
101 #include "ace/Log_Msg.h"
102 #include "ace/Signal.h"
105 class Sig_Handler_1 : public ACE_Event_Handler
107 public:
108 Sig_Handler_1 (ACE_Reactor &reactor, const char *msg)
109 : msg_ (msg),
110 count_ (0),
111 reactor_ (reactor)
113 // Register the signal handlers.
114 this->quit_sigkey_ =
115 reactor.register_handler (SIGQUIT, this);
116 this->int_sigkey_ =
117 reactor.register_handler (SIGINT, this);
119 if (this->quit_sigkey_ == -1 || this->int_sigkey_ == -1)
120 ACE_ERROR ((LM_ERROR,
121 "%p\n",
122 "register_handler"));
125 // @@ Note that this code is not portable to all OS platforms since
126 // it does print statements within the signal handler.
127 virtual int handle_signal (int signum, siginfo_t *, ucontext_t *)
129 this->count_++;
130 ACE_DEBUG ((LM_DEBUG,
131 "\nsignal %S occurred in Sig_Handler_1 (%s, %d, %d) with count = %d",
132 signum,
133 this->msg_,
134 this->int_sigkey_,
135 this->quit_sigkey_,
136 this->count_));
138 if (this->count_ != 1 && signum == SIGQUIT)
140 if (this->reactor_.remove_handler (SIGQUIT,
143 this->quit_sigkey_) == -1)
144 ACE_ERROR ((LM_ERROR,
145 "\n%p",
146 "remove_handler"));
147 else
148 ACE_DEBUG ((LM_DEBUG,
149 "\nshutting down SIGQUIT in Sig_Handler_1 (%s, %d, %d)",
150 this->msg_,
151 this->int_sigkey_,
152 this->quit_sigkey_));
154 else if (this->count_ != 2 && signum == SIGINT)
156 if (this->reactor_.remove_handler (SIGINT,
159 this->int_sigkey_) == -1)
160 ACE_ERROR ((LM_ERROR,
161 "\n%p",
162 "remove_handler"));
163 else
164 ACE_DEBUG ((LM_DEBUG,
165 "\nshutting down SIGINT in Sig_Handler_1 (%s, %d, %d)",
166 this->msg_,
167 this->int_sigkey_,
168 this->quit_sigkey_));
170 return 0;
173 protected:
174 const char *msg_;
175 int count_;
176 int int_sigkey_;
177 int quit_sigkey_;
178 ACE_Reactor &reactor_;
181 class Sig_Handler_2 : public Sig_Handler_1
183 public:
184 Sig_Handler_2 (ACE_Reactor &reactor, const char *msg)
185 : Sig_Handler_1 (reactor, msg)
189 virtual int handle_signal (int signum, siginfo_t *, ucontext_t *)
191 this->count_++;
192 ACE_DEBUG ((LM_DEBUG,
193 "\nsignal %S occurred in Sig_Handler_2 (%s, %d, %d) with count = %d",
194 signum,
195 this->msg_,
196 this->int_sigkey_,
197 this->quit_sigkey_,
198 this->count_));
199 if (this->count_ != 0 && signum == SIGQUIT)
201 if (this->reactor_.remove_handler (SIGQUIT, 0, 0, this->quit_sigkey_) == -1)
202 ACE_ERROR ((LM_ERROR,
203 "\n%p",
204 "remove_handler"));
205 else
206 ACE_DEBUG ((LM_DEBUG,
207 "\nshutting down SIGQUIT in Sig_Handler_2 (%s, %d, %d)",
208 this->msg_,
209 this->int_sigkey_,
210 this->quit_sigkey_));
212 return 0;
216 static void
217 external_handler (int signum)
219 ACE_DEBUG ((LM_DEBUG,
220 "\nsignal %S occurred in external handler!",
221 signum));
225 ACE_TMAIN (int argc, ACE_TCHAR *[])
227 // If argc > 1 then allow multiple handlers per-signal, else just
228 // allow 1 handler per-signal.
229 ACE_Sig_Handlers multi_handlers;
231 #if defined (ACE_WIN32)
232 ACE_WFMO_Reactor reactor_impl (argc > 1
233 ? &multi_handlers
234 : (ACE_Sig_Handler *) 0);
235 #else
236 ACE_Select_Reactor reactor_impl (argc > 1
237 ? &multi_handlers
238 : (ACE_Sig_Handler *) 0);
239 #endif /* ACE_WIN32 */
240 ACE_Reactor reactor (&reactor_impl);
242 if (argc > 1)
244 // Register an "external" signal handler so that the
245 // ACE_Sig_Handlers code will have something to incorporate!
247 ACE_SignalHandler eh = (ACE_SignalHandler) external_handler;
248 ACE_Sig_Action sa (eh);
250 sa.register_action (SIGINT);
253 // Create a bevy of handlers.
254 Sig_Handler_1 h1 (reactor, "howdy");
255 Sig_Handler_1 h2 (reactor, "doody");
256 Sig_Handler_2 h3 (reactor, "tutty");
257 Sig_Handler_2 h4 (reactor, "fruity");
259 // Wait for user to type SIGINT and SIGQUIT.
261 for (;;)
263 ACE_DEBUG ((LM_DEBUG,
264 "\nwaiting for SIGINT or SIGQUIT\n"));
266 if (reactor.handle_events () == -1)
267 ACE_ERROR ((LM_ERROR,
268 "%p\n",
269 "handle_events"));
272 ACE_NOTREACHED (return 0);