Directory
- 1. Srand () and Rand () functions and random number seeds
- 2. Daemon and PID files
- 3. Signal processing when initializing the server
- 4. Log stack information when the program Coredump StackTrace
1. Srand () and Rand () functions and random number seeds
srand(time(NULL)^getpid());struct timeval tv;gettimeofday(&tv,NULL);dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid());
2. Daemon and PID files
In the main () function, the configuration file determines whether to run in daemon mode.
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. Signal processing when initializing the server
// 初始化服务器函数void initServer(void) { // 忽视信号: SIGHUP, SIGPIPE signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); // 设置SIGTERM, SIGINT 信号处理函数 setupSignalHandlers();
//Set signal processing function, when Sigtern, SIGINT, exit program void Setupsignalhandlers (void) {struct Sigaction act; /* When the SA_SIGINFO flag are 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;}
Signal processing function, CTRL + C will produce SIGINT signal, two consecutive times, will exit the program. 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 waitin G to persist * on disk. */if (Server.shutdown_asap && sig = = SIGINT) {Redislogfromhandler (redis_warning, "you insist ... Exitin G now. "); Rdbremovetempfile (Getpid ()); Exit (1); /* Exit with the error since this is not a clean shutdown. */} else if (server.loading) {exit (0); } redislogfromhandler (redis_warning, msg); After receiving the sigterm/sigint signal, the SERVER.SHUTDOWN_ASAP is set to 1 in the signal processing function; The next time you run the Servercron function, the value is checked and the program exits safely. SERVER.SHUTDOWN_ASAP = 1;}
4. Log stack information when the program 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);}
(i) Redis source reading