失败/退出时监视并重新启动子进程 [英] Monitoring and restarting child process when fails/exits

查看:160
本文介绍了失败/退出时监视并重新启动子进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个简单的示例,监视子进程并在失败或退出时重新启动它.这样做的首选/更可靠的方法是什么?持续轮询状态变化是否是一种好习惯?我的理解是,我应该使用SIGCHLD之类的东西,但一直找不到任何好的例子.

我主要是一名嵌入式C编码器,这是我第一次尝试理解fork().此代码的目的最终将是监视使用exec()的另一个程序的调用,并在出现以下情况时重新启动该程序:当它失败或结束时.

修改: 在@cnicutar发表评论后,我以一种更有意义的方式重写了下面的示例,希望该示例对以后的用户有用.我希望父进程监视子进程,同时进行其他操作,并在子进程失败/完成时在新的fork上对exec进行新调用.我想尝试并使用Unix信号来实现这一目标

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char *argv[])
{
    pid_t cpid;
    int status;
    cpid = fork();
    for (;;)
    {
        switch (cpid)
        {
        case -1 : //Fork failure
            exit(EXIT_FAILURE);
            break;

        case 0 : //Child Process
            exec(some function);
            return 0; //exit child process
            break;

        default : //Parent process
            if (waitpid(-1, &status, WNOHANG) != 1) cpid = fork(); //restart 
            //Do parent stuff here...
            break;
        }
    }
}

解决方案

添加SIGCHLD处理程序不会给您带来多少好处,因为您已经一直等待着并且只能这样做-没有其他事情可以中断"了./p>

我建议的一件事是设置一个阈值,以使该进程不会死机/启动太频繁.

我的理解是,我应该利用SIGCHLD之类的东西,但是 找不到任何好的例子

您使用SIGCHLD知道何时等待.典型的SIGCHLD处理程序只是循环执行waitpid,直到没有子级为止.在您的情况下,您不需要这样做,因为您的主要代码是在waitpid上停止的循环.


编辑

您可以找到很多有关SIGCHLD处理的示例.一个这样的例子是如何在C语言中处理sigchld .在该代码中,在while之后,您只需fork:

while((pid = waitpid(-1, &status, WNOHANG)) > 0)
        ;

pid = fork();
switch (pid)
...

重申一下,如果执行此操作,每次孩子死亡时都会调用SIGCHLD,并且在正确等待它之后,您可以fork另一个.只有在父母与此同时有更好的事情要做而不是仅仅对waitpid进行阻止时,这才有意义.


明智的话.某些功能不能从信号处理程序中调用,以免在程序中添加困难的错误.查找异步信号安全"功能:只能从信号处理程序中调用这些功能,并且只有这些功能可以调用.某些最常见的功能(例如printfmalloc)无法从信号处理程序中调用.

I've created a rudimentary example of monitoring a child process and restarting it when it fails or exits. What is the preferred/more robust method of doing this? Is it good practice to continuously poll for a change in status? My understanding is that I should utilize something like SIGCHLDbut have been unable to find any good examples.

I'm an embedded C coder mainly and this is my first attempt at trying to understand fork().The purpose of this code will eventually be to monitor a call to another program using exec() and restart this program if and when it fails or finishes.

Edit: After comments from @cnicutar I have rewritten the example below in a way I think makes more sense in the hope that it is of use to somebody later. I would like the parent to monitor a child process whilst foing other things and make a new call to exec on a new fork when the child process fails/finishes. I want to try and use unix signals to achieve this

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char *argv[])
{
    pid_t cpid;
    int status;
    cpid = fork();
    for (;;)
    {
        switch (cpid)
        {
        case -1 : //Fork failure
            exit(EXIT_FAILURE);
            break;

        case 0 : //Child Process
            exec(some function);
            return 0; //exit child process
            break;

        default : //Parent process
            if (waitpid(-1, &status, WNOHANG) != 1) cpid = fork(); //restart 
            //Do parent stuff here...
            break;
        }
    }
}

解决方案

Adding a SIGCHLD handler won't buy you much since you already wait all the time and only do that - there's nothing else to "interrupt".

One thing I would suggest is a threshold such that the process doesn't die/start too often.

My understanding is that I should utilize something like SIGCHLD but have been unable to find any good examples

You use SIGCHLD to know when to wait. A typical SIGCHLD handler just does waitpid in a loop until no children are left. In your case you don't need that since your main code is a loop stopped on waitpid.


EDIT

You can find plenty of examples for SIGCHLD handling. One such example is How can I handle sigchld in C. In that code, after the while you can just fork:

while((pid = waitpid(-1, &status, WNOHANG)) > 0)
        ;

pid = fork();
switch (pid)
...

To reiterate, if you do this SIGCHLD will be called every time a child dies and after you properly wait for it you can just fork another. This only makes sense if the parent has better stuff to do in the meantime than to just block on waitpid.


Word to the wise. There are certain functions that must not be called from a signal handler lest you add difficult bugs to your program. Look up "async signal safe" functions: these and only these can be called from a signal handler. Some of the most common functions (like printf and malloc) cannot be called from a signal handler.

这篇关于失败/退出时监视并重新启动子进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆