I am writing a program that must run several processes and perform specific manipulations with them. The goal: to start several processes, to complete the execution of some processes (we choose ourselves), they should start again. Those. we are trying to shut down processes, and they are being renewed all the time. For one process, the program is working properly. If I run several processes, the program works properly only for the first running process, the other processes are safely closed. Debug results: I found out that all processes (except the first one created in main-e) do not satisfy the condition waitpid (-1, & child_status, WNOHANG) == pid. Honestly, I can not understand why. Thank you in advance.

#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(); } 

1 answer 1

You incorrectly use waitpid . By setting the -1 status check to be performed for all child processes and the completed process may not coincide with the process for which this object is responsible. There is no check for errors at all.

 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(); // сюда не должны попасть 

And it is better to stuff processes into set and look in it using the result waitpid instead of calling it for each process.

  • Thanks for the answer. Please tell me why we use in the first parameter waitpid () not the values ​​that are specified in the manual (0.-1, <- 1, etc.), but exactly pid by value. - oddz
  • @oddz Um, this is the value that is indicated in the manual. A specific pid should be set when you need to know the status of a specific process. - VTT