Управление процессами Linux C++

257
21 февраля 2018, 10:53

Пишу программу,которая должна запускать несколько процессов и выполнять конкретную манипуляцию с ними. Цель: запустить несколько процессов, завершить выполнение некоторых процессов(сами выбираем) ,они должны запуститься заново. Т.е. мы пытаемся закрыть процессы, а они все время возобновляются. Для одного процесса программа работает исправно. Если запускаю несколько процессов, то программа работает исправно только для первого запускающегося процесса, остальные процессы благополучно закрываются. Результаты дебага: я выяснил что все процессы(кроме первого, созданного в main-e) не удовлетворяют условие waitpid(-1,&child_status,WNOHANG)==pid . Честно, не могу понять почему. Заранее спасибо.

#include <iostream>
#include <set>
#ifndef SUBPROCESS_H_
#define SUBPROCESS_H_
class Subprocess { //класс подпроцесс
public:
    Subprocess(const char* name_of_child_process); // конструктор с параметром, в параметры принимает имя процесса, который запускаем
    Subprocess(const Subprocess & obj);
    ~Subprocess();
    void Create_Process();
    void handle_signal(int signal);
    static void signal_handler(int signal);
    void spawn();
private:
    pid_t pid;
    const char* cmdline;
    static std::set<Subprocess*> s_processes;
};

#endif /* SUBPROCESS_H_ */

    /*
 * Subprocess.cpp
 *
 *  
 *      Author: dmitriy
 */
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <csignal>
#include "Subprocess.h"
#include <vector>
#include <memory>
using namespace std;
void Subprocess::signal_handler(int signal)
{
    cout<<"I am a signal handler"<<endl;
    for (auto* sp : s_processes)
    {
        sp->handle_signal(signal);
    }
}
Subprocess::Subprocess(const char* name_of_child_process)
{
    cout<<"Default constructor"<<endl;
    s_processes.emplace(this);
    //vec_processes.push_back(this);
    cmdline=name_of_child_process;
    spawn();
}
void Subprocess::spawn()
{
    pid=fork();
    if (pid==-1) cout<<"Error ,process not fork"<<endl;
    else if (pid==0)
    {
        cout <<"I am children process"<<getpid()<<"  My pa_pid "<<getppid()<<endl;
        execlp("env", "env", cmdline, NULL);
    }
    else
    {
        cout<<"I am a parent with pid "<<getpid()<<endl;
    }
}
void Subprocess::handle_signal(int signal)
{
    cout<<"In handle_signal"<<endl;
    if (signal == SIGCHLD) {
        int child_status;
    if (waitpid(-1, &child_status, WNOHANG) == pid) {
            cout << "child pid=" << pid << " is gone" << endl;
            spawn();
            cout<<"WIFEEXITED- "<<WIFEXITED(child_status)<<endl;
            cout<<"WEXITSTATUS- "<<WEXITSTATUS(child_status)<<endl;
            cout<<"WIFSIGNALED- "<<WIFSIGNALED(child_status)<<endl;
            cout<<"WTERMSIG- "<<WTERMSIG(child_status)<<endl;
        }
    }
}
Subprocess::~Subprocess()
{
    s_processes.erase(this);
    kill(pid,SIGTERM);
}
std::set<Subprocess*> Subprocess::s_processes;
vector<shared_ptr<Subprocess> > processes;
int main()
{
    signal(SIGCHLD, Subprocess::signal_handler);
    Subprocess process("firefox");
    Subprocess process_1("xclock");

//  processes.push_back(make_shared<Subprocess>("xclock"));
    for (;;)
        {
        }
//  processes.push_back(make_shared<Subprocess>("firefox"));
//  pause();
}
Answer 1

Вы неправильно используете waitpid. Выставляя -1 проверка статуса осуществляться для всех дочерних процессов и завершившийся процесс может не совпадать с процессом, за который отвечает этот объект. Проверка на ошибки вообще отсутствует.

errno = 0;
auto const wait_result{::waitpid(pid, &child_status, WNOHANG)};
if(wait_result < 0) // ошибка
{
    auto const last_error{errno};
    throw ::std::system_error{last_error, ::std::system_category{}, "waitpid failed"};
}
if(0 == wait_result) // ничего не произошло
{
    return;
} 
if(pid == wait_result) // дочерний процесс завершился
{
    // обработка...
    return;
}  
::std::abort(); // сюда не должны попасть

А лучше запихивать процессы в set и искать в нем использую результат waitpid вместо вызывания его для каждого процесса.

READ ALSO
Вопрос по обучению [требует правки]

Вопрос по обучению [требует правки]

Я буду летом поступать в УниверситетДумаю выбороть для себя именно С++

216
C++ GLUT Как передать метод класса в в glutDisplayFunc (без &ldquo;invalid use of non-static member function&rdquo;)

C++ GLUT Как передать метод класса в в glutDisplayFunc (без “invalid use of non-static member function”)

Здравствуйте я использую GLUT и C++У меня есть класс App с методом Render, и я хочу его передать в glutDisplayFunc, но при попытках:

254
QGamepad после переподключение не обределяется

QGamepad после переподключение не обределяется

Такая проблема, имеется класс gamepadmonitor из примеров qtПри запуске программы, если джостик отключен и следом его подключить, программа на это...

243
Как упаковать класс c++/cli и передать как указатель в неуправляемый метод

Как упаковать класс c++/cli и передать как указатель в неуправляемый метод

Можно ли, и как упаковать каким-то образом объект управляемый в указатель, и передать его в неуправляемый объект, что бы неуправляемый объект...

237