From 638e14bbf375a1ff5b8776c21632bc445a1f36d3 Mon Sep 17 00:00:00 2001 From: Paul Kulchenko Date: Sat, 23 Jul 2022 18:58:31 -0700 Subject: [PATCH] Improve Redbean shutdown (#506) * Update redbean shutdown to call OnServerStop when all shutdown/logging is done * Move closing file descriptors during daemonization earlier This should fix using opened file descriptors, for example, SQLite DB files and redbean itself when StoreAsset is used. Fixes #182. * Move opening logs earlier to capture logs from Listen and .init.lua * Move pidpath handling outside of daemonize, as it can be used independently --- tool/net/redbean.c | 68 ++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 82ebeff30..b9bba8c9b 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -1012,6 +1012,8 @@ static void ProgramHeader(const char *s) { static void ProgramLogPath(const char *s) { logpath = strdup(s); + close(2); + open(logpath, O_APPEND | O_WRONLY | O_CREAT, 0640); } static void ProgramPidPath(const char *s) { @@ -1043,27 +1045,10 @@ static void ChangeUser(void) { } static void Daemonize(void) { - char ibuf[21]; - int i, fd, pid; - for (i = 0; i < 256; ++i) { - if (!IsServerFd(i)) { - close(i); - } - } - if ((pid = fork()) > 0) exit(0); + if (fork() > 0) exit(0); setsid(); - if ((pid = fork()) > 0) _exit(0); + if (fork() > 0) _exit(0); umask(0); - if (pidpath) { - fd = open(pidpath, O_CREAT | O_WRONLY, 0644); - WRITE(fd, ibuf, FormatInt32(ibuf, getpid()) - ibuf); - close(fd); - } - if (!logpath) ProgramLogPath("/dev/null"); - open("/dev/null", O_RDONLY); - open(logpath, O_APPEND | O_WRONLY | O_CREAT, 0640); - dup2(1, 2); - ChangeUser(); } static void LogLuaError(char *hook, char *err) { @@ -7058,6 +7043,7 @@ static void HandleShutdown(void) { KillGroup(); } WaitAll(); + INFOF("(srvr) shutdown complete"); } // this function coroutines with linenoise @@ -7294,6 +7280,8 @@ static void GetOpts(int argc, char *argv[]) { } void RedBean(int argc, char *argv[]) { + char ibuf[21]; + int fd; if (IsLinux()) { // disable weird linux capabilities for (int e = errno, i = 0;; ++i) { @@ -7315,6 +7303,15 @@ void RedBean(int argc, char *argv[]) { (shared = mmap(NULL, ROUNDUP(sizeof(struct Shared), FRAMESIZE), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0))); + if (daemonize) { + for (int i = 0; i < 256; ++i) { + if (!IsServerFd(i)) { + close(i); + } + } + open("/dev/null", O_RDONLY); + open("/dev/null", O_WRONLY); + } zpath = GetProgramExecutableName(); CHECK_NE(-1, (zfd = open(zpath, O_RDONLY))); CHECK_NE(-1, fstat(zfd, &zst)); @@ -7332,6 +7329,10 @@ void RedBean(int argc, char *argv[]) { if (uniprocess) { shared->workers = 1; } + if (daemonize) { + if (!logpath) ProgramLogPath("/dev/null"); + dup2(2, 1); + } SigInit(); Listen(); TlsInit(); @@ -7340,13 +7341,13 @@ void RedBean(int argc, char *argv[]) { } if (daemonize) { Daemonize(); - } else { - if (logpath) { - close(2); - open(logpath, O_APPEND | O_WRONLY | O_CREAT, 0640); - } - ChangeUser(); } + if (pidpath) { + fd = open(pidpath, O_CREAT | O_WRONLY, 0644); + WRITE(fd, ibuf, FormatInt32(ibuf, getpid()) - ibuf); + close(fd); + } + ChangeUser(); UpdateCurrentDate(nowl()); CollectGarbage(); hdrbuf.n = 4 * 1024; @@ -7378,15 +7379,6 @@ void RedBean(int argc, char *argv[]) { ReplEventLoop(); } #endif - if (!isexitingworker) { - HandleShutdown(); - CallSimpleHookIfDefined("OnServerStop"); - } - if (!IsTiny()) { - LuaDestroy(); - TlsDestroy(); - MemDestroy(); - } if (!isexitingworker) { if (!IsTiny()) { terminatemonitor = true; @@ -7395,9 +7387,13 @@ void RedBean(int argc, char *argv[]) { #ifndef STATIC _join(&replth); #endif + HandleShutdown(); + CallSimpleHookIfDefined("OnServerStop"); } - if (!isexitingworker) { - INFOF("(srvr) shutdown complete"); + if (!IsTiny()) { + LuaDestroy(); + TlsDestroy(); + MemDestroy(); } }