Restart child process
От: Handler Украина  
Дата: 03.10.13 04:56
Оценка:
Здравствуйте!
Задача:
следить за дочерним процессом и перезапускать его в случае завершения.
Я принял следующий подход к этой задаче:

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


#define NUM_THREADS 3
    
    
    struct Arg {
        pid_t pid;
    };
    

void* product(void* arg) {
    while (1) {
        // do smth complex
        sleep(1);
        printf("process %d\n", getpid());
    }
}


void* control(void* arg) {
    int status;
    pid_t w;
    
    do {
        w = waitpid((((Arg*)arg)->pid), &status, WUNTRACED | WCONTINUED );
        if (w == -1) {
            perror("waitpid");
            exit(EXIT_FAILURE);
        }
        
        if (WIFEXITED(status)) {
            printf("exited, status=%d\n", WEXITSTATUS(status));
        } else if (WIFSIGNALED(status)) {
            printf("killed by signal %d\n", WTERMSIG(status));
        } else if (WIFSTOPPED(status)) {
            printf("stopped by signal %d\n", WSTOPSIG(status));
        } else if (WIFCONTINUED(status)) {
            printf("continued\n");
        }
        
    } while (!WIFEXITED(status) && !WIFSIGNALED(status));
    exit(EXIT_SUCCESS);
}


void startProcess() {
    pid_t cpid;//, w;
    pthread_t thread;
    //int status;
    cpid = fork();
    if (cpid == -1) {
        perror("fork");
        printf("WE SHOULD RESTART PROCESS\n");
        exit(EXIT_FAILURE);
    }
    if (cpid == 0) {            // Code executed by child
        printf("Child PID is %ld\n", (long) getpid());
        Arg arg;
        arg.pid = cpid;
        pthread_create(&thread,0, &product, &arg);
    }
    else {                    // Code executed by parent
        Arg arg;
        arg.pid = cpid;
        pthread_create(&thread,0, &control, &arg);
        return;
    }
}

int main() {
        for(int i=0; i<NUM_THREADS; ++i) {
            startProcess();
        }
    return 0;
}


Насколько я понял, данный подход не совсем правильный.
Возможно, вы можете указать на мои ошибки и подсказать правильный путь.
Спасибо
Алексей

03.10.13 15:49: Перенесено модератором из 'C/C++' — Кодт
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Re: Restart child process
От: Razzak  
Дата: 22.10.13 11:32
Оценка:
Здравствуйте, Handler, Вы писали:

H>Здравствуйте!

H>Задача:
H>следить за дочерним процессом и перезапускать его в случае завершения.

Дарю:
#/bin/bash

while /bin/true; do
  process
done



H>Я принял следующий подход к этой задаче:


H>#define NUM_THREADS 3


Использовать вперемешку треды и форки — значит нарываться на грабли.


void startProcess() {
    pid_t cpid;//, w;
    pthread_t thread;
    //int status;
    cpid = fork();
    if (cpid == -1) {
        perror("fork");
        printf("WE SHOULD RESTART PROCESS\n");
        exit(EXIT_FAILURE);
    }
    if (cpid == 0) {            // Code executed by child
        printf("Child PID is %ld\n", (long) getpid());
        Arg arg;
        arg.pid = cpid;
        pthread_create(&thread,0, &product, &arg);
    }
    else {                    // Code executed by parent
        Arg arg;
        arg.pid = cpid;
        pthread_create(&thread,0, &control, &arg);
        return;
    }
}


Зачем здесь треды и какая польза ожидается от их применения?


int main() {
        for(int i=0; i<NUM_THREADS; ++i) {
            startProcess();
        }
    return 0;
}

Программа запустит несколько тредов (если успеет — тред не обязан стартовать сразу же), после чего тут же преспокойно завершится (треды, которые успели запуститься, благополучно сдохнут на первом же cancellation point).

Как минимум , было бы неплохо подождать завершения работы треда (pthread_join()).

H>Насколько я понял, данный подход не совсем правильный.

H>Возможно, вы можете указать на мои ошибки и подсказать правильный путь.

Ошибки:
— Для этой задачи не нужны треды
— Для этой задачи не нужен С, достаточно простенького скрипта на шелле.
— Но даже если вдруг очень-очень надо написать такой враппер на С, запускать процесс в юниксах принято через идиому fork+exec, а не через треды-бреды. Т.е. форкаемся, проверяем pid, и если мы в потомке — замещаем текущий процесс нужной программой через exec*().

Правильный путь:
— Не изобретать велосипед, а использовать имеющуюся в вашем дистрибутиве линукса/юникса обвязку для запуска демонов ака сервисов (сейчас пошла мода называть демонов "сервисами" — линукс становится дружелюбнее к религиозно одаренным).
— Если очень надо именно свой лисапет (стандартная обвязка не подходит), то все равно правильнее такие вещи делать на шелле, а не компилябельным бинарем.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.