FBB::Fork - Implements fork(2) using the Template Design Pattern
Contents
Bobcat
Bobcat is an acronym of `Brokken’s Own Base Classes And Templates’.
Bobcat Project Files
o https://fbb-git.gitlab.io/bobcat/: gitlab project page;
Debian Bobcat project files:
o libbobcat6: debian package containing the shared library, changelog and copyright note;
o libbobcat-dev: debian package containing the static library, headers, manual pages, and developer
info;
Bugs
None Reported.
Constructors
Only the default constructor is available.
Copyright
This is free software, distributed under the terms of the GNU General Public License (GPL).
Description
FBB::Fork objects may be used to implement the fork(2) call as part of the Template Algorithm Design Pattern. The class was designed as a virtual base class for classes implementing the essential parts of the forking process. The class is a virtual base class. Derived classes must implement the members childProcess and parentProcess as part of the `Template Method Design Pattern’ (see Gamma etal., 1995). Terminating child processes send SIGCHLD signals to their parents. The C library offers the following macros to analyze the status values received by the parent process using a wait(2) or waitpid(2) system call: o intWIFEXITED(intstatus): This macro returns a nonzero value if the child process terminated normally with `exit’ or `_exit’. o intWEXITSTATUS(intstatus): If `WIFEXITED’ is true of `status’, this macro returns the low-order 8 bits of the exit status value from the child process. o intWIFSIGNALED(intstatus): This macro returns a nonzero value if the child process terminated because it received a signal that was not handled. o intWTERMSIG(intstatus): If `WIFSIGNALED’ is true of `status’, this macro returns the signal number of the signal that terminated the child process. o intWCOREDUMP(intstatus): This macro returns a nonzero value if the child process terminated and produced a core dump. o intWIFSTOPPED(intstatus): This macro returns a nonzero value if the child process is stopped. o intWSTOPSIG(intstatus): If `WIFSTOPPED’ is true of `status’, this macro returns the signal number of the signal that caused the child process to stop.
Destructor
o virtual~Fork():
Derived classes may define their own destructor, which is called when the Fork destructor is
activated.
Examples
#include <iostream>
#include <unistd.h>
#include <bobcat/fork>
using namespace std;
using namespace FBB;
class Background: public Fork
{
public:
void childProcess() override;
void parentProcess() override;
};
void Background::childProcess()
{
for (int idx = 0; idx < 3; ++idx)
{
cout << "Hello world # " << idx << endl;
sleep(1);
}
throw 0; // caught in main()
}
void Background::parentProcess()
{
cout << "Waiting for the child process to end...\n"
"The child returns value " << waitForChild() << endl;
}
int main()
try
{
Background bg;
bg.fork();
cout << "This is from the parent\n";
}
catch(int x)
{
cout << "The child terminates with: " << x << endl;
return x;
}
Here’s a more extensive example:
#include <iostream>
#include <string>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <bobcat/pipe>
#include <bobcat/ofdstream>
#include <bobcat/ifdstream>
#include <bobcat/process>
#include <bobcat/fork>
class ChildIO: public FBB::Fork
{
FBB::Pipe childInput; // child reads this
FBB::Pipe childOutput; // child writes this
public:
void childRedirections() override;
void childProcess() override;
void parentProcess() override;
};
using namespace std;
using namespace FBB;
void ChildIO::childRedirections()
{
childInput.readFrom(Redirector::STDIN);
childOutput.writtenBy(Redirector::STDOUT);
}
void ChildIO::childProcess()
{
// The /bin/cat program replaces the
// child process started by Fork::fork()
Process process(Process::DIRECT, "/bin/cat");
process.start();
// this point is never reached
}
void ChildIO::parentProcess()
{
// Set up the parent’s sides of the pipes
IFdStream fromChild(childOutput.readOnly());
OFdStream toChild(childInput.writeOnly());
// write lines to the child, read its output
string line;
while (true)
{
cout << "? ";
line.clear();
getline(cin, line);
if (line.empty())
{
kill(pid(), SIGTERM);
break;
}
toChild << line << endl;
getline(fromChild, line);
cout << "Got: " << line << endl;
}
cout << "The child returns value " << waitForChild() << endl;
}
int main()
try
{
ChildIO io;
io.fork();
return 0;
}
catch(exception const &exc)
{
cerr << "Exception: " << exc.what() << endl;
}
catch(int x)
{
cout << "The child terminates with: " << x << endl;
return x;
}
Files
bobcat/fork - defines the class interface
Inherits From
-
Member Functions
o voidfork():
Performs the actual forking. It is implemented in such a way that the corresponding parent- and
child- processes are activated from virtual members of Fork. If the forking operation fails, an
FBB::Exception exception is thrown.
Name
FBB::Fork - Implements fork(2) using the Template Design Pattern
Namespace
FBB
All constructors, members, operators and manipulators, mentioned in this man-page, are defined in the
namespace FBB.
Private (Virtual) Member Functions
o virtualvoidchildProcess()=0:
This member must be implemented by derived classes. It defines the actions that are performed by
the child process, following the fork(2) system call. Just before childProcess is called,
childRedirections (see below) has been executed. The childProcess() function should terminate the
child process. A good way to do this is to throw an exception which is caught by main()’s function
try block. Terminating a process using exit(2) is deprecated in C++.
o virtualvoidchildRedirections():
This function may be redefined in derived classes to set up the redirections that are necessary to
communicate with the parent process. See also the classes redirector(3bobcat) and pipe(3bobcat).
By default, childRedirections does nothing.
o virtualvoidparentProcess()=0:
This member must be implemented by derived classes. It defines the actions that are performed by
the parent process, following the fork(2) system call. Just before parentProcess is called,
parentRedirections (see below) has been executed.
When deriving classes from Fork their parentProcess implementation preferably handles all actions
to perform by the parent process. If the child process remains active when the parent process
decides that the program has performed its duties (e.g., the child process is replaced by a
program started by an exec.. function, continuously producing output, interpreted by the parent
process) then the parent process can call endChild to end the child process before ending the
parentProcess function.
o virtualvoidparentRedirections():
This function may be redefined in derived classes to set up the redirections that are necessary to
communicate with, e.g., the parent. See, e.g., the classes redirector(3bobcat) and pipe(3bobcat).
By default, parentRedirections does nothing.
Protected Member Functions
o intendChild()const:
This member may be called by parentProcess to end the child process. To end the child process a
SIGTERM is sent to the child process, followed by a SIGKILL (cf. signal(7)). If the child process
has already ended then the child process’s exit value is returned, otherwise the child process’s
end is forced (by calling kill) and -2 is returned. This member also calls waitForChild (see
below).
o pid_tpid()const:
Returns the child’s process id in the parent’s code (i.e., in the parent-members below), and 0 in
the child’s code (i.e., in the child-members below). The pid member returns -1 when called before
the member fork has been called.
o voidprepareDaemon()const:
Prepares for a daemon childprocess. This function may (should) be called from childProcess to
ensure that the child process changes its current working directory to the root (/) directory,
thus freeing up mount points; that the child process starts a new session/process group to allow
the parent (group leader) to kill all its processes without terminating the daemon; and makes sure
that the child process closes and reopens the standard streams by associating them with /dev/null
to prevent ghost input and output actions from interfering with the daemon’s actions. An
FBB::Exception is thrown if changing directory to the root directory fails.
o voidprepareDaemon(std::stringconst&out,std::stringconst&err,mode_tmode=0600)const:
Prepares for a daemon childprocess like the previous member function, but allows redirection of
the standard output (out) and standard error (err) streams to files. Specify empty strings to
redirect these streams to /dev/null. With non-empty strings the specified files are opened in
append-mode (and created if not yet existing), by default using mode 0600 (read/write mode for the
user only). An FBB::Exception is thrown if changing directory to the root directory or if using
the specified s fails.
o intwaitForChild()const:
This member may be called by parentProcess to wait for the completion of the child-process. The
return value (exit-code) of the child process is returned as a value between 0 and 255. If the
child process terminates before the completion of the parent process, then waitForChild should be
called to prevent zombies from occurring. Alternatively, the parent process may terminate (e.g.,
using exit(2)) while the child process is still alive. This is the normal way to create a daemon
process.
See Also
bobcat(7), cerrextractor(3bobcat), cininserter(3bobcat), coutextractor(3bobcat), exec(3), exec(3bobcat), fork(2), kill(2), pipe(3bobcat), redirector(3bobcat), stdextractor(3bobcat), wait(2), waitpid(2).
Synopsis
#include<bobcat/fork>
Linking option: -lbobcat