1 initdb 之信号处理
在函数void initialize_data_directory(void) 中先后有如下函数
setup_signals();
check_ok();
以下分别介绍
1.1setup_signals()
void setup_signals(void) { /* some of these are not valid on Windows */ #ifdef SIGHUP pqsignal(SIGHUP,trapsig); #endif #ifdef SIGINT pqsignal(SIGINT,trapsig); #endif #ifdef SIGQUIT pqsignal(SIGQUIT,trapsig); #endif #ifdef SIGTERM pqsignal(SIGTERM,trapsig); #endif /* Ignore SIGPIPE when writing to backend,so we can clean up */ #ifdef SIGPIPE pqsignal(SIGPIPE,SIG_IGN); #endif }
1.1.1 有关信号参见《unix 环境高级编程》 P236 Second edition
SIGHUP : 如果终端接口检测到一个连接断开,则将该信号发送给与该终端相关的控制进程(会话首进程)。
如果会话首进程终止,则也将产生此信号,在这种情况下,此信号将被发送给前台进程组中的每一个进程。
SIGINT: 当用户按中断键(一般采用ctrl+c 或delete)时,终端驱动程序将产生此信号并发送至前台进程组中的每一个进程。
SIGQUIT: 当用户在终端上按退出键(一般采用ctrl+\)时,产生此信号,并发送至前台进程组中的所有进程。此信号不仅会终止前台进程组(如SIGINT所作的那样),还会产生 core文件。
SIGTERM:这是kill(1) 命令发送的系统默认终止信号
SIGPIPE: 如果在写到管道时进程已终止,则产生此信号。当类型为SOCK_STREAM的套接字已不再连接时,进程写到该套接字也产生此信号。
1.1.2 函数trapsig()
/* * signal handler in case we are interrupted. * * The Windows runtime docs at * http://msdn.microsoft.com/library/en-us/vclib/html/_crt_signal.asp * specifically forbid a number of things being done from a signal handler,* including IO,memory allocation and system calls,and only allow jmpbuf * if you are handling SIGFPE. * * I avoided doing the forbidden things by setting a flag instead of calling * exit_nicely() directly. * * Also note the behavIoUr of Windows with SIGINT,which says this: * Note SIGINT is not supported for any Win32 application,including * Windows 98/Me and Windows NT/2000/XP. When a CTRL+C interrupt occurs,* Win32 operating systems generate a new thread to specifically handle * that interrupt. This can cause a single-thread application such as UNIX,* to become multithreaded,resulting in unexpected behavior. * * I have no idea how to handle this. (Strange they call UNIX an application!) * So this will need some testing on Windows. */ static void trapsig(int signum) { /* handle systems that reset the handler,like Windows (grr) */ pqsignal(signum,trapsig); caught_signal = true; }
这里关键是将bool类型 cought_signal 赋值为true
1.1.3 函数pgsignal()
/* * Unix-like signal handler installation * * Only called on main thread,no sync required */ pqsigfunc pqsignal(int signum,pqsigfunc handler) { pqsigfunc prevfunc; if (signum >= PG_SIGNAL_COUNT || signum < 0) return SIG_ERR; prevfunc = pg_signal_array[signum]; pg_signal_array[signum] = handler; return prevfunc; }
1.2 函数 check_ok()
/* * call exit_nicely() if we got a signal,or else output "ok". */ static void check_ok(void) { if (caught_signal) { printf(_("caught signal\n")); fflush(stdout); exit_nicely(); } else if (output_Failed) { printf(_("could not write to child process: %s\n"),strerror(output_errno)); fflush(stdout); exit_nicely(); } else { /* all seems well */ printf(_("ok\n")); fflush(stdout); } }
1.2.1 函数exit_nicely()
/* * clean up any files we created on failure * if we created the data directory remove it too */ static void exit_nicely(void) { if (!noclean) { if (made_new_pgdata) { fprintf(stderr,_("%s: removing data directory \"%s\"\n"),progname,pg_data); if (!rmtree(pg_data,true)) fprintf(stderr,_("%s: Failed to remove data directory\n"),progname); } else if (found_existing_pgdata) { fprintf(stderr,_("%s: removing contents of data directory \"%s\"\n"),false)) fprintf(stderr,_("%s: Failed to remove contents of data directory\n"),progname); } if (made_new_xlogdir) { fprintf(stderr,_("%s: removing transaction log directory \"%s\"\n"),xlog_dir); if (!rmtree(xlog_dir,_("%s: Failed to remove transaction log directory\n"),progname); } else if (found_existing_xlogdir) { fprintf(stderr,_("%s: removing contents of transaction log directory \"%s\"\n"),_("%s: Failed to remove contents of transaction log directory\n"),progname); } /* otherwise died during startup,do nothing! */ } else { if (made_new_pgdata || found_existing_pgdata) fprintf(stderr,_("%s: data directory \"%s\" not removed at user's request\n"),pg_data); if (made_new_xlogdir || found_existing_xlogdir) fprintf(stderr,_("%s: transaction log directory \"%s\" not removed at user's request\n"),xlog_dir); } exit(1); }