@@ -66,22 +66,56 @@ static void ignoreSigpipe()
6666 sa.sa_flags = 0 ;
6767 sa.sa_handler = SIG_IGN ;
6868 if (0 != sigaction (SIGPIPE , &sa, NULL )) {
69- bsl::cerr << " Failed to ignore SIGPIPE!"
70- << " \n " ;
69+ bsl::cerr << " Failed to ignore SIGPIPE!" << bsl::endl;
7170 }
7271#endif
7372}
7473
75- // Raw pointer to the semaphore to keep the application alive
76- static BloombergLP::bslmt::Semaphore* s_shutdownSemaphore_p = 0 ;
74+ class ShutdownContext {
75+ public:
76+ // PUBLIC DATA
77+
78+ // / The semaphore that keeps the application alive.
79+ bslmt::Semaphore d_appSemaphore;
80+
81+ // / The number of times a user tried to close bmqtool.
82+ bsls::AtomicInt d_shutdownCount;
83+
84+ // CREATORS
85+ ShutdownContext ()
86+ : d_appSemaphore(0 )
87+ , d_shutdownCount(0 ){
88+ // NOTHING
89+ };
90+ };
91+
92+ static ShutdownContext* s_shutdownContext_p = 0 ;
7793
7894extern " C" {
7995static void shutdownApp (int sig)
8096{
81- bsl::cerr << " Signal " << sig << " - shutting down..."
82- << " \n " ;
83- if (s_shutdownSemaphore_p) {
84- s_shutdownSemaphore_p->post ();
97+ // The number of received signals for immediate termination.
98+ static const int k_NUM_TO_TERMINATE = 5 ;
99+
100+ if (s_shutdownContext_p) {
101+ const int numRetries = s_shutdownContext_p->d_shutdownCount .addRelaxed (
102+ 1 );
103+ if (k_NUM_TO_TERMINATE <= numRetries) {
104+ bsl::cerr << " Received a signal [" << sig << " ] " << numRetries
105+ << " times, terminating immediately" << bsl::endl;
106+ bsl::exit (128 + sig);
107+ }
108+ else {
109+ bsl::cerr << " Received a signal [" << sig << " ], shutting down... "
110+ << " Please send a signal "
111+ << k_NUM_TO_TERMINATE - numRetries
112+ << " more times to terminate immediately" << bsl::endl;
113+ s_shutdownContext_p->d_appSemaphore .post ();
114+ }
115+ }
116+ else {
117+ bsl::cerr << " No shutdown context provided to handle a signal [" << sig
118+ << " ]" << bsl::endl;
85119 }
86120}
87121} // close extern "C"
@@ -417,6 +451,9 @@ int main(int argc, const char* argv[])
417451 bool isInteractive = parameters.mode () == ParametersMode::e_CLI ||
418452 parameters.mode () == ParametersMode::e_STORAGE;
419453
454+ ShutdownContext shutdownContext;
455+ s_shutdownContext_p = &shutdownContext;
456+
420457 // If we are running in interactive mode, we don't want to intercept
421458 // ctrl-C, the application will exit on ctrl-D from the stdin stream
422459 if (!isInteractive) {
@@ -426,17 +463,15 @@ int main(int argc, const char* argv[])
426463 signal (SIGTERM , shutdownApp);
427464 }
428465
429- bslmt::Semaphore shutdownSemaphore (0 );
430- s_shutdownSemaphore_p = &shutdownSemaphore;
431466 bslma::Allocator* allocator = parameters.memoryDebug ()
432467 ? &ta
433468 : bslma::Default::allocator ();
434469
435- Application app (parameters, &shutdownSemaphore , allocator);
470+ Application app (parameters, &shutdownContext. d_appSemaphore , allocator);
436471 if (app.start () != 0 ) {
437472 return 2 ; // RETURN
438473 }
439- shutdownSemaphore .wait ();
474+ shutdownContext. d_appSemaphore .wait ();
440475 app.stop ();
441476
442477 // Memory debugging
0 commit comments