標籤:live handle set eof ddr stat with psi temp
目錄
- 1. srand()和rand()函數以及隨機數種子
- 2. 守護進程及pid檔案
- 3. 初始化伺服器時的訊號處理
- 4. 在程式coredump時記錄堆棧資訊StackTrace
1. srand()和rand()函數以及隨機數種子
srand(time(NULL)^getpid());struct timeval tv;gettimeofday(&tv,NULL);dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid());
2. 守護進程及pid檔案
在main()函數中,通過設定檔判斷是否以守護進程模式運行。
if (server.daemonize) daemonize(); // 守護進程if (server.daemonize) createPidFile(); // 記錄pid的檔案
// 將程式以守護進程方式運行void daemonize(void) { int fd; if (fork() != 0) exit(0); /* parent exits */ setsid(); /* create a new session */ /* Every output goes to /dev/null. If Redis is daemonized but * the ‘logfile‘ is set to ‘stdout‘ in the configuration file * it will not log at all. */ if ((fd = open("/dev/null", O_RDWR, 0)) != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if (fd > STDERR_FILENO) close(fd); }}// 儲存進程ID到檔案void createPidFile(void) { /* Try to write the pid file in a best-effort way. */ FILE *fp = fopen(server.pidfile,"w"); if (fp) { fprintf(fp,"%d\n",(int)getpid()); fclose(fp); }}
3. 初始化伺服器時的訊號處理
// 初始化伺服器函數void initServer(void) { // 忽視訊號: SIGHUP, SIGPIPE signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); // 設定SIGTERM, SIGINT 訊號處理函數 setupSignalHandlers();
// 設定訊號處理函數,當SIGTERN, SIGINT時,退出程式void setupSignalHandlers(void) { struct sigaction act; /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction is used. * Otherwise, sa_handler is used. */ sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = sigShutdownHandler; sigaction(SIGTERM, &act, NULL); sigaction(SIGINT, &act, NULL);#ifdef HAVE_BACKTRACE sigemptyset(&act.sa_mask); act.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO; act.sa_sigaction = sigsegvHandler; sigaction(SIGSEGV, &act, NULL); sigaction(SIGBUS, &act, NULL); sigaction(SIGFPE, &act, NULL); sigaction(SIGILL, &act, NULL);#endif return;}
// 訊號處理函數,ctrl+c 會產生 SIGINT訊號,連續兩次,會退出程式。static void sigShutdownHandler(int sig) { char *msg; switch (sig) { case SIGINT: msg = "Received SIGINT scheduling shutdown..."; break; case SIGTERM: msg = "Received SIGTERM scheduling shutdown..."; break; default: msg = "Received shutdown signal, scheduling shutdown..."; }; /* SIGINT is often delivered via Ctrl+C in an interactive session. * If we receive the signal the second time, we interpret this as * the user really wanting to quit ASAP without waiting to persist * on disk. */ if (server.shutdown_asap && sig == SIGINT) { redisLogFromHandler(REDIS_WARNING, "You insist... exiting now."); rdbRemoveTempFile(getpid()); exit(1); /* Exit with an error since this was not a clean shutdown. */ } else if (server.loading) { exit(0); } redisLogFromHandler(REDIS_WARNING, msg); // 在接收到SIGTERM/SIGINT訊號後,在訊號處理函數中將server.shutdown_asap置為1; // 當下次運行serverCron函數時,會檢查該值,然後安全退出程式。 server.shutdown_asap = 1;}
4. 在程式coredump時記錄堆棧資訊StackTrace
/* Logs the stack trace using the backtrace() call. This function is designed * to be called from signal handlers safely. */void logStackTrace(ucontext_t *uc) { void *trace[100]; int trace_size = 0, fd; int log_to_stdout = server.logfile[0] == ‘\0‘; /* Open the log file in append mode. */ fd = log_to_stdout ? STDOUT_FILENO : open(server.logfile, O_APPEND|O_CREAT|O_WRONLY, 0644); if (fd == -1) return; /* Generate the stack trace */ trace_size = backtrace(trace, 100); /* overwrite sigaction with caller‘s address */ if (getMcontextEip(uc) != NULL) trace[1] = getMcontextEip(uc); /* Write symbols to log file */ backtrace_symbols_fd(trace, trace_size, fd); /* Cleanup */ if (!log_to_stdout) close(fd);}
(一)redis源碼閱讀