Skip to content

Commit c1ddd33

Browse files
authored
Feat[bmqtool]: allow fast shutdown in AUTO mode (#866)
Signed-off-by: Evgeny Malygin <emalygin@bloomberg.net>
1 parent 744ec95 commit c1ddd33

1 file changed

Lines changed: 47 additions & 12 deletions

File tree

src/applications/bmqtool/bmqtool.m.cpp

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

7894
extern "C" {
7995
static 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

Comments
 (0)