I have made a class that is supposed to handle a subprocess but when I put a test print inside nothing happens, can someone tell me why ?
I have tried different types of print and combinations of fflush but it didn't solve the problem.
Here are my files:
Kitchen.cpp
Kitchen::Kitchen()
{
int wstatus;
this->_pid = fork();
if (this->_pid == 0) {
std::cout << "child: " << this->_pid << std::endl;
} else if (this->_pid == -1) {
throw("No child");
} else {
std::cout << "parent: " << this->_pid << std::endl;
waitpid(this->_pid, &wstatus, 1);
}
}
Kitchen::~Kitchen()
{
if (this->_pid > 0)
kill(this->_pid, SIGKILL);
}
Kitchen.hpp
#pragma once
#include <signal.h>
#include <unistd.h>
class Kitchen {
public:
Kitchen();
~Kitchen();
private:
pid_t _pid;
};
Reception.cpp
int Reception::run_shell(void)
{
this->_kitchens.push_back(Kitchen());
return (0);
}
Reception.hpp
#pragma once
#include <iostream>
#include <sstream>
#include "Kitchen.hpp"
class Reception
{
public:
Reception();
~Reception();
void repart(std::vector<Package> packed_order);
bool is_order(std::string input);
std::vector<Package> pack(std::string input);
int run_shell(void);
private:
std::vector<Kitchen> _kitchens;
};
main.cpp
int main(void)
{
Reception reception;
return (reception.run_shell());
}
Right now only the parent prints where as I would like both process to print.
Note that this code works outside of the class.
is it better now ?
Yes, better.
I copied your code to my Lubuntu 18.04, and using g++ 7.3.0-27, got the thing to compile.
The copied code on my system reproduced your error.
Hmmm.
So, I went looking for, and quickly found, my most recent experiment with fork. I do not understand why it works, and yours does not, they look similar enough to me.
I use a switch instead of your nested if-then-else's ... perhaps there exists a glitch in the nested if-then-else's? a faulty char transfer? But I doubt it.
So ... for pragmatic reasons, I (minimally?) changed your code to match my example.
Perhaps you can ask a better question as to why this seems to work, and in your version does not.
Hope this helps:
#include "../../bag/src/dtb_chrono.hh"
using namespace std::chrono_literals; // support suffixes like 100ms, 2s, 30us
#include <iostream>
using std::cout, std::cerr, std::flush, std::endl;
#include <string>
using std::string;
#include <thread>
using std::this_thread::sleep_for;
#include <vector>
using std::vector;
#include <cstring>
using std::strerror;
#include <unistd.h> // fork
#include <sys/wait.h> // waitpid
#include <cassert>
class Kitchen
{
pid_t child_pid;
time_t pt0; // child start time 0
time_t ct0; // parent start time 0
public:
Kitchen()
{
pt0 = time(0) + 2;
ct0 = time(0) + 1;
// On success, the PID of the child process is returned in the
// parent, and 0 is returned in the child.
//
// On failure, -1 is returned in the parent, no child process is
// created, and errno is set appropriately.
child_pid = fork();
switch (child_pid)
{
case -1: { errnoExit (errno, "\n fork fail: ", -12); } break;
case 0: // child
{
std::cout << "\n i am child: " << child_pid << endl;
ChildProcess();
}
break;
default: // parent
{
std::cout << "\n i am parent, child_pid: " << child_pid << flush;
ParentProcess();
}
} // switch(child_pid)
} // Kitchen
~Kitchen()
{
if (child_pid > 0)
{ }; // { kill(child_pid, SIGKILL)};
}
void ChildProcess(void)
{
int i = 0;
do {
i += 1;
cout << "\n child " << i;
std::this_thread::sleep_for(100ms);
if (time(0) > ct0) break;
}while (true);
cout << "\n*** Child complete ***" << '\n';
}
void ParentProcess(void)
{
int i = 0;
do {
i += 1;
cout << "\n parent " << i ;
std::this_thread::sleep_for(100ms);
if (time(0) > pt0) break;
}while (true);
int wstatus;
waitpid(child_pid, &wstatus, 1); // see output -
// waitpid not effective because parent runs longer than child
// but causes no harm ...
//
// TBD - when parent run is shorter than child?
// appears that parent end halts child?
cout << "\n*** Parent complete ***" << '\n';
}
private:
void errnoExit(int err_no, const string message, int id) {
assert(0 != err_no); cerr << message << strerror(err_no);
assert(id < 0); exit(id); }
}; // class Kitchen
class Reception
{
public:
Reception() = default;
~Reception() = default;
int operator()(int argc, char* argv[]) { return run_shell(argc, argv); }
//void repart(std::vector<Package> packed_order);
//bool is_order(std::string input);
//std::vector<Package> pack(std::string input);
int run_shell(int /*argc*/, char** /*argv[]*/)
{
_kitchens.push_back(Kitchen());
return (0);
}
private:
vector<Kitchen> _kitchens;
}; // class Reception
int main(int argc, char* argv[]) { return Reception()(argc, argv); }
Typical Output:
i am parent, child_pid: 6727
i am child: 0
parent 1
child 1
parent 2
child 2
parent 3
child 3
parent 4
child 4
parent 5
child 5
parent 6
child 6
parent 7
child 7
parent 8
child 8
parent 9
child 9
parent 10
child 10
parent 11
child 11
parent 12
child 12
parent 13
child 13
parent 14
child 14
parent 15
child 15
parent 16
child 16
parent 17
child 17
parent 18
child 18
*** Child complete ***
parent 19
parent 20
parent 21
parent 22
parent 23
parent 24
parent 25
parent 26
parent 27
parent 28
*** Parent complete ***