postgres 之 initdb 源码分析 八

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);
}

1.3 在initdb如何引起信号中断产生

在initdb时,在执行过程中按下ctrl+c 或者ctrl+\ 就会看到调用函数exit_nicely()

相关文章

项目需要,有个数据需要导入,拿到手一开始以为是mysql,结果...
本文小编为大家详细介绍“怎么查看PostgreSQL数据库中所有表...
错误现象问题原因这是在远程连接时pg_hba.conf文件没有配置正...
因本地资源有限,在公共测试环境搭建了PGsql环境,从数据库本...
wamp 环境 这个提示就是说你的版本低于10了。 先打印ph...
psycopg2.OperationalError: SSL SYSCALL error: EOF detect...