PostgreSQL的信号处理机制

信号是一种软件中断机制,是linux很重要的一种进程间通信方式,很多重要的应用程序都需要处理信号。PostgreSQL在启动Postmaster主进程时注册信号处理函数。

一、PostgreSQL安装信号的实现方法

在linux中使用signal()和sigaction()函数安装信号。PostgreSQL定义了pgsignal函数实现信号的安装。

pgsignal的定义

如果当前的系统不遵循POSIX标准,例如一些早期的Unix系统,PG使用signal安装信号和信号处理程序,signal的第一个参数指定信号值,第二个参数指定针对前面信号值的处理程序,也可以忽略该信号(参数设为SIG_IGN);

对于遵循POSIX标准的操作系统,则使用sigaction安装信号。上面的代码定义了两个结构为sigaction的实例act和oact。act的sa_handler可以是用户自定义的处理函数外,还可以为SIG_DFL(缺省处理方式),也可以为SIG_IGN(忽略信号)。

sigaction函数的第一个signo参数指定信号值,第二个参数&act是指向结构sigaction的一个实例的指针;第三个参数&oact指向的对象不为空,用来保存原来对相应信号的处理。 pgsignal返回的是pgsigfunc,pgsigfunc只是一个简单的函数指针:

等价于:

二、PostgreSQL变更了哪些信号的处理

PostgreSQL在PostmasterMain入口函数中注册信号处理函数,也可以称为安装信号。

我把这段代码总结了一张图表,方便了解PostgreSQL对系统信号的变更。

在PostmasterMain函数中更改这12个信号的默认处理方式为6种信号处理程序。

SIGHUP在控制TTY断开连接时的默认处理方式为终止进程,更改为SIGHUP_handler。

SIGHUP_handler负责重新装载配置文件,包括hba文件,并告知子进程做同样的事情。
SIGINT,SIGTERM,SIGQUIT的默认处理方式更改为pmdie。

pmdie干的事情很多。简单总结一下就是对SIGINT,SIGTERM,SIGQUIT的处理方式对应PostgreSQL的三种关闭方式:Smart/Fast/Immediate Shutdown Mode.文档对这三种关闭方式描述非常清楚: http://www.postgresql.org/docs/devel/static/server-shutdown.html
SIGALRM,SIGPIPE,SIGTTIN,SIGTTOU,SIGXFSZ这几个信号均被忽略。
SIGUSR1的默认处理程序更改为sigusr1_handler,用来处理来自子进程的信号。
SIGUSR2的默认处理程序更改为dummy_handler,我很想用“顾名思义”这个成语来描述我看到这个函数名称的第一感觉,不过还是很好奇的看看代码来验证感觉。

它果然是个空函数,实际上什么都没有做。这是为什么呢?对于实际上并不在postmaster进程使用的信号使用dummy_handler作为信号处理程序。
reaper用来处理子进程挂掉后的善后事项,也就是俗称擦屁股的,处理子进程的信号及部分内容比较多,需要专门写一篇笔记来梳理。

三、精简后的PostmasterMain函数

这个精简的PostmasterMain函数只描述了信号的处理部分。

PostmasterMain通过以下步骤完成信号的处理:

pginitmask()

pginitmask()函数用来设置阻塞信号集(sig set)和不阻塞信号集,这里有三个信号集:UnBlockSig,BlockSig,StartupBlockSig。

PG_SETMASK()

PG_SETMASK()函数把BlockSig信号集中的信号全部屏蔽。PG_SETMASK()为不同的OS采用了不同的处理方式,谁让PG是世界上支持操作系统最多的数据库系统呢。在类UNIX中,它只是sigsetmask(),在windows中它是pgsigsetmask()。

pgsignal()

安装表中描述的各种信号。

四、其他

以上就是PG对信号的处理。这里主要讨论了在Linux系统的处理,对于windows系统,则是模拟一个类似lunix信号的消息队列出来,在src/backend/port/win32/signal.c的代码,是在win32中模拟linux信号的一些函数,关于windows相关的内容,我没有深入了解了。

五、精简的PostmasterMain的实现

附上一个最精简的PostmasterMain的实现,只安装了一个SIGHUP信号。

2019更新:

编译

运行

在当前终端按下终止符或者在其他终端向他发出不同信号进行观察和实验。