【发布时间】:2011-02-26 16:53:48
【问题描述】:
任何人都可以发布一些示例代码,说明如何在守护程序收到 SIGHUP 信号后重新读取配置文件并重新启动我的守护程序。守护进程是Linux上用C语言编写的用户空间程序,不是由inetd启动的。
【问题讨论】:
-
人们通常不希望守护进程在收到 SIGHUP 时重新启动,而是会进行优雅的重新加载,即加载新的配置文件但不会丢弃连接的客户端和类似的坏事。
任何人都可以发布一些示例代码,说明如何在守护程序收到 SIGHUP 信号后重新读取配置文件并重新启动我的守护程序。守护进程是Linux上用C语言编写的用户空间程序,不是由inetd启动的。
【问题讨论】:
根据您的程序编写的干净程度,有(至少)三种方法可以做到这一点:
收到信号后,在初始化阶段之前返回程序的开头(可能 - 但不一定 - 通过 setjmp()/longjmp() 或 sigsetjmp()/siglongjmp() 对) ,从而重置并重新读取配置文件。
收到信号后,让信号处理程序再次执行原始程序。这具有丢失所有状态并将所有全局变量和静态变量重置回其原始状态的优点。它的缺点是丢失了之前的所有状态。
也许第三个选项不那么残酷;它会注意到信号已被接收,并且在主处理循环中的下一个方便点,将返回并重新读取配置文件。
有效的部分取决于您的守护程序必须执行的操作。如果它花时间与客户交谈,您可能不想使用选项 1 或 2 - 您更愿意使用选项 3。如果您要一次性回答简单问题,那么残酷的方法可能是有效(并且可能更易于编程)。请注意,选项 1 需要仔细处理 WIP(正在进行的工作)和诸如打开文件之类的事情 - 如果您不小心,您将失去对资源的跟踪,并且守护程序将失败(内存不足,文件描述符不足 -很可能是这两者之一)。
【讨论】:
取决于你如何构建它;如果您在单个线程/进程中处理多个连接,那么您可能应该在重新加载配置(或 exec 本身)之前以某种方式通知它们退出(如果可以的话;取决于协议)。
如果协议允许您说“走开,稍后再回来”,那么显然这样做是一个很好的胜利。如果客户端需要保持连接,您可以将配置更改应用于已连接的客户端,如果它是单进程单线程守护程序,如果这有意义的话。
如果是多进程,事情会变得更加复杂。您必须通知进程有关新配置的信息,或确保它们继续使用旧配置,或者他们可以在客户端退出时选择新配置。
如果是多线程,线程需要能够在它们碰巧正在做的任何事情的中间安全地读取新配置,这可能需要锁定,或者您可以为新的配置结构分配内存并执行以某种方式切换,
【讨论】:
我在自己寻找示例以确保我做的正确时发现了这个页面。由于没有示例,因此我将发布我的尝试并让其他人对此发表评论:
volatile sig_atomic_t g_eflag = 0;
volatile sig_atomic_t g_hupflag = 1;
static void signal_handler(int sig)
{
switch(sig)
{
case SIGHUP:
g_hupflag = 1;
break;
case SIGINT:
case SIGTERM:
g_eflag = 1;
break;
}
}
int main(int argc, char **argv)
{
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
signal(SIGPIPE, SIG_IGN);
while(!g_eflag)
{
if(g_hupflag)
{
g_hupflag = 0;
load_config();
}
// ... do daemon work ...
}
return 0;
}
【讨论】:
【讨论】: