首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

Redis2.2.2源码学习——信号的处置

2013-10-18 
Redis2.2.2源码学习——信号的处理Redis对信号的处理如下:1)忽略的信号:SIGHUP(终端session关闭)、SIGPIPE(管

Redis2.2.2源码学习——信号的处理
Redis对信号的处理如下:


1)忽略的信号:SIGHUP(终端session关闭)、SIGPIPE(管道错误)


2)出错相关信号:SIGSEGV SIGBUS SIGFPE SIGILL
处理方式:触发段错误的处理函数中,
1.主要将错误信息写入日志 
2.将该信号处理信号设置为默认,重新在本身发送该信号(执行信号的默认处理)


3)进程结束信号:SIGTERM(该信号用于请求中止进程,kill命令缺省发送)
1.server.shutdown_asap = 1; 和程序出错信号相比,SIGTERM属于正常的终止信号。所以
信号处理函数没有执行系统的默认信号处理函数。而是在serverCron()函数中,调用
prepareForShutdown()函数处理服务器推出前的后续工作,最后退出。


4)其他信号: 执行默认处理


p.s.  http://blog.chinaunix.net/uid-24599332-id-2122898.html
1) SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。
2) SIGSEGV(Segment fault)意味着指针所对应的地址是无效地址,没有物理内存对应该地址。
3) SIGFPE(floating-point exception)算术错误

4) SIGILL(illegal instruction)执行非法指令


--------------------------initServer------------------------------------------void initServer() {...    signal(SIGHUP, SIG_IGN);    signal(SIGPIPE, SIG_IGN);    setupSigSegvAction();...}void setupSigSegvAction(void) {    struct sigaction act;    sigemptyset (&act.sa_mask);    /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction     * is used. Otherwise, sa_handler is used */    act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;    act.sa_sigaction = segvHandler;    sigaction (SIGSEGV, &act, NULL);//段    sigaction (SIGBUS, &act, NULL);//总线    sigaction (SIGFPE, &act, NULL);//算术    sigaction (SIGILL, &act, NULL);//指令    sigaction (SIGBUS, &act, NULL);//两个BUS ?    act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;    act.sa_handler = sigtermHandler;    sigaction (SIGTERM, &act, NULL);//请求服务器终止    return;}----------------------程序出错相关信号的hander---------------------------------/*1.写服务器出错日志  2.再次执行信号的默认操作(为了core dump?)。  作者的解释:Make sure we exit with the right signal at the end. So for instance  the core will be dumped if enabled.  比如:(http://zh.wikipedia.org/wiki/SIGSEGV)  在一个程序接收到SIGSEGV时的默认动作是异常终止。这个动作也许会结束进程,  但是可能生成一个核心文件(core file)以帮助调试,或者执行一些其他特定于某些平台的动作。例如,  使用了grsecurity补丁的Linux系统可能记录SIGSEGV信号以监视可能的使用缓存溢出的攻击尝试。*/void segvHandler(int sig, siginfo_t *info, void *secret) {    void *trace[100];    char **messages = NULL;    int i, trace_size = 0;    ucontext_t *uc = (ucontext_t*) secret;    sds infostring;    struct sigaction act;    REDIS_NOTUSED(info);    redisLog(REDIS_WARNING,        "======= Ooops! Redis %s got signal: -%d- =======", REDIS_VERSION, sig);    infostring = genRedisInfoString();    redisLog(REDIS_WARNING, "%s",infostring);    /* It's not safe to sdsfree() the returned string under memory     * corruption conditions. Let it leak as we are going to abort */    trace_size = backtrace(trace, 100);    /* overwrite sigaction with caller's address */    if (getMcontextEip(uc) != NULL) {        trace[1] = getMcontextEip(uc);    }    messages = backtrace_symbols(trace, trace_size);    for (i=1; i<trace_size; ++i)        redisLog(REDIS_WARNING,"%s", messages[i]);    /* free(messages); Don't call free() with possibly corrupted memory. */    if (server.daemonize) unlink(server.pidfile);    /* Make sure we exit with the right signal at the end. So for instance     * the core will be dumped if enabled. */ //由于前面篡改了信号处理函数,为何程序按照正常的处理方式退出,这里采用 //将信号处理函数修改为默认,再次向本进程发送该信号,从而执行信号的默认操作(core dump)    sigemptyset (&act.sa_mask);    /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction     * is used. Otherwise, sa_handler is used */    act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;    act.sa_handler = SIG_DFL;    sigaction (sig, &act, NULL);    kill(getpid(),sig);}-----------------------SIGTERM信号的hander-----------------------------------------------//shutdown_asap作为服务器是否进入退出状态的标志//作者并未在该hander中直接调用服务器退出函数,而仅仅是设置了退出标志。真正的退出在serverCron中调用//作者这样安排估计是为了程序的规范吧?不知道还有没有其他意义...void sigtermHandler(int sig) {    REDIS_NOTUSED(sig);    redisLog(REDIS_WARNING,"SIGTERM received, scheduling shutting down...");    server.shutdown_asap = 1;}-----------------------serverCron---------------------------//serverCron作为定时器事件(服务器的协调员,啥事都管)//在下一次执行是检测到server.shutdown_asap==1,那么执行退出操作int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {.../* We received a SIGTERM, shutting down here in a safe way, as it is     * not ok doing so inside the signal handler. */    if (server.shutdown_asap) {        if (prepareForShutdown() == REDIS_OK) exit(0);        redisLog(REDIS_WARNING,"SIGTERM received but errors trying to shut down the server, check the logs for more information");    }...}


热点排行