任何人都可以发布一些示例代码,说明如何在守护程序收到SIGHUP信号后重新读取配置文件并重新启动守护程序。守护进程是一个用C语言编写的用户空间程序,不是由inetd启动的。
答案 0 :(得分:6)
根据您的程序编写的干净程度,有(至少)三种方法:
收到信号后,在初始化阶段之前返回程序的开头(可能 - 但不一定 - 通过setjmp()/ longjmp()或sigsetjmp()/ siglongjmp()对) ,从而重置和重新读取配置文件。
收到信号后,让信号处理程序再次执行原始程序。这具有丢失所有状态并将所有全局变量和静态变量重置回其原始状态的优点。它有失去所有以前状态的缺点。
第三种选择可能不那么残酷;它会注意到信号已被接收,并且在主处理循环中的下一个方便点,将返回并重新读取配置文件。
什么有效取决于你的守护进程必须做什么。如果它花时间与客户进行对话,您可能不想使用选项1或2中的任何一个 - 您更愿意使用选项3.如果您对简单问题做一次性回答,那么残酷的方法可能是有效(并且可能更容易编程)。请注意,选项1需要仔细处理WIP(正在进行的工作)和诸如打开文件之类的事情 - 如果您不小心,您将失去对资源的跟踪,并且守护程序将失败(内存不足,文件描述符之外 - 很可能是这两个中的一个。)
答案 1 :(得分:1)
我找到了这个页面,因为我自己正在寻找一个例子,以确保我正确地做到了。由于没有这方面的例子,我会发布我的尝试并让其他人评论它:
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;
}
答案 2 :(得分:1)
答案 3 :(得分:0)
取决于你如何构建它;如果你在一个线程/进程中处理多个连接,那么在重新加载配置(或exec本身)之前,你应该以某种方式通知它们退出(如果你可以;依赖于协议)。
如果协议允许你说“离开并稍后回来”,那么显然这样做是一个很好的胜利。如果客户端需要保持连接,则可以将配置更改应用于已连接的客户端(如果它是单进程单线程守护程序,如果这有意义的话。)
如果是多个过程,事情变得更加复杂。您必须通知流程有关新配置,或确保他们继续使用旧配置,或者他们可以在客户端退出时选择新配置。
如果它是多线程,则线程需要安全地能够在它们正在进行的任何操作中读取新配置,这可能需要锁定,或者您可以为新的配置结构分配内存并执行转换某种方式,