1 // Test the ability of the Reactor/Signal_Handler to register multiple
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
19 To run this version of the test do the following:
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
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
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:
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
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
108 Sig_Handler_1 (ACE_Reactor
&reactor
, const char *msg
)
113 // Register the signal handlers.
115 reactor
.register_handler (SIGQUIT
, this);
117 reactor
.register_handler (SIGINT
, this);
119 if (this->quit_sigkey_
== -1 || this->int_sigkey_
== -1)
120 ACE_ERROR ((LM_ERROR
,
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
*)
130 ACE_DEBUG ((LM_DEBUG
,
131 "\nsignal %S occurred in Sig_Handler_1 (%s, %d, %d) with count = %d",
138 if (this->count_
!= 1 && signum
== SIGQUIT
)
140 if (this->reactor_
.remove_handler (SIGQUIT
,
143 this->quit_sigkey_
) == -1)
144 ACE_ERROR ((LM_ERROR
,
148 ACE_DEBUG ((LM_DEBUG
,
149 "\nshutting down SIGQUIT in Sig_Handler_1 (%s, %d, %d)",
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
,
164 ACE_DEBUG ((LM_DEBUG
,
165 "\nshutting down SIGINT in Sig_Handler_1 (%s, %d, %d)",
168 this->quit_sigkey_
));
178 ACE_Reactor
&reactor_
;
181 class Sig_Handler_2
: public Sig_Handler_1
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
*)
192 ACE_DEBUG ((LM_DEBUG
,
193 "\nsignal %S occurred in Sig_Handler_2 (%s, %d, %d) with count = %d",
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
,
206 ACE_DEBUG ((LM_DEBUG
,
207 "\nshutting down SIGQUIT in Sig_Handler_2 (%s, %d, %d)",
210 this->quit_sigkey_
));
217 external_handler (int signum
)
219 ACE_DEBUG ((LM_DEBUG
,
220 "\nsignal %S occurred in external handler!",
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
234 : (ACE_Sig_Handler
*) 0);
236 ACE_Select_Reactor
reactor_impl (argc
> 1
238 : (ACE_Sig_Handler
*) 0);
239 #endif /* ACE_WIN32 */
240 ACE_Reactor
reactor (&reactor_impl
);
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.
263 ACE_DEBUG ((LM_DEBUG
,
264 "\nwaiting for SIGINT or SIGQUIT\n"));
266 if (reactor
.handle_events () == -1)
267 ACE_ERROR ((LM_ERROR
,
272 ACE_NOTREACHED (return 0);