diff options
author | Alex Zolotarev <alex@maps.me> | 2015-07-08 18:16:36 +0300 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 02:55:20 +0300 |
commit | fdb7b8f75f0c35fc15e3a267fe169ef094441286 (patch) | |
tree | d6d268954aa705b5635b9f6c8b63df882918e6cc /3party | |
parent | 466e288248537fc96def9f95052823c1c09fd550 (diff) |
[alohalytics] Graceful FastCGI server stop on SIGTERM and SIGINT.
Diffstat (limited to '3party')
-rw-r--r-- | 3party/Alohalytics/server/fcgi_server.cc | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/3party/Alohalytics/server/fcgi_server.cc b/3party/Alohalytics/server/fcgi_server.cc index 3ee52ea799..fd29dba4b5 100644 --- a/3party/Alohalytics/server/fcgi_server.cc +++ b/3party/Alohalytics/server/fcgi_server.cc @@ -139,6 +139,17 @@ int main(int argc, char * argv[]) { ALOG(" - SIGHUP reopens main data file and SIGUSR1 reopens debug log file for logrotate utility."); return -1; } + int result = FCGX_Init(); + if (0 != result) { + ALOG("ERROR: FCGX_Init has failed with code", result); + return result; + } + FCGX_Request request; + result = FCGX_InitRequest(&request, 0, FCGI_FAIL_ACCEPT_ON_INTR); + if (0 != result) { + ALOG("ERROR: FCGX_InitRequest has failed with code", result); + return result; + } // Redirect cout into a file if it was given in the command line. CoutToFileRedirector log_redirector(argc > 2 ? argv[2] : nullptr); @@ -150,18 +161,26 @@ int main(int argc, char * argv[]) { if (SIG_ERR == ::signal(SIGUSR1, [](int) { gReceivedSIGUSR1 = SIGUSR1; })) { ATLOG("WARNING: Can't set SIGUSR1 handler. Logrotate will not work correctly."); } - - int result = FCGX_Init(); - if (0 != result) { - ALOG("ERROR: FCGX_Init has failed with code", result); - return result; - } - FCGX_Request request; - result = FCGX_InitRequest(&request, 0, FCGI_FAIL_ACCEPT_ON_INTR); - if (0 != result) { - ALOG("ERROR: FCGX_InitRequest has failed with code", result); - return result; + // NOTE: On most systems, when we get a signal, FCGX_Accept_r blocks even with a FCGI_FAIL_ACCEPT_ON_INTR flag set + // in the request. Looks like on these systems default signal function installs the signals with the SA_RESTART flag + // set (see man sigaction for more details) and syscalls are automatically restart themselves if a signal occurs. + // To "fix" this behavior and gracefully shutdown our server, we use a trick from + // W. Richard Stevens, Stephen A. Rago, "Advanced Programming in the UNIX Environment", 2nd edition, page 329. + // It is also described here: http://comments.gmane.org/gmane.comp.web.fastcgi.devel/942 + for (auto signo : {SIGTERM, SIGINT}) { + struct sigaction act; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; +#ifdef SA_INTERRUPT + act.sa_flags |= SA_INTERRUPT; +#endif + act.sa_handler = [](int) { FCGX_ShutdownPending(); }; + const int result = sigaction(signo, &act, nullptr); + if (result != 0) { + ATLOG("WARNING: Can't set", signo, "signal handler"); + } } + alohalytics::StatisticsReceiver receiver(argv[1]); string gzipped_body; long long content_length; |