加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgres 之 initdb 源码分析 八

发布时间:2020-12-13 17:28:36 所属栏目:百科 来源:网络整理
导读:1 initdb 之信号处理 在函数void initialize_data_directory(void) 中先后有如下函数 setup_signals(); check_ok(); 以下分别介绍 1.1setup_signals() voidsetup_signals(void){/* some of these are not valid on Windows */#ifdef SIGHUPpqsignal(SIGHUP,t

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 signaln"));
		fflush(stdout);
		exit_nicely();
	}
	else if (output_failed)
	{
		printf(_("could not write to child process: %sn"),strerror(output_errno));
		fflush(stdout);
		exit_nicely();
	}
	else
	{
		/* all seems well */
		printf(_("okn"));
		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 directoryn"),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 directoryn"),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 directoryn"),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 directoryn"),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 requestn"),pg_data);

		if (made_new_xlogdir || found_existing_xlogdir)
			fprintf(stderr,_("%s: transaction log directory "%s" not removed at user's requestn"),xlog_dir);
	}

	exit(1);
}

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读