FBB::Fork(3bobcat)
Template Design Pattern around fork(2)
(libbobcat-dev_6.04.00)
2005-2023
NAME
FBB::Fork - Implements fork(2) using the Template Design Pattern
SYNOPSIS
#include <bobcat/fork>
Linking option: -lbobcat
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 et al., 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:
- int WIFEXITED(int status):
This macro returns a nonzero value if the child process terminated
normally with `exit' or `_exit'.
- int WEXITSTATUS(int status):
If `WIFEXITED' is true of `status', this macro returns the
low-order 8 bits of the exit status value from the child process.
- int WIFSIGNALED(int status):
This macro returns a nonzero value if the child process terminated
because it received a signal that was not handled.
- int WTERMSIG(int status):
If `WIFSIGNALED' is true of `status', this macro returns the
signal number of the signal that terminated the child process.
- int WCOREDUMP(int status):
This macro returns a nonzero value if the child process terminated
and produced a core dump.
- int WIFSTOPPED(int status):
This macro returns a nonzero value if the child process is stopped.
- int WSTOPSIG(int status):
If `WIFSTOPPED' is true of `status', this macro returns the signal
number of the signal that caused the child process to stop.
NAMESPACE
FBB
All constructors, members, operators and manipulators, mentioned in this
man-page, are defined in the namespace FBB.
INHERITS FROM
-
CONSTRUCTORS
Only the default constructor is available.
DESTRUCTOR
- virtual ~Fork():
Derived classes may define their own destructor, which is called when
the Fork destructor is activated.
MEMBER FUNCTIONS
- void fork():
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.
PROTECTED MEMBER FUNCTIONS
- int endChild() 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).
- pid_t pid() 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.
- void prepareDaemon() 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.
- void prepareDaemon(std::string const &out, std::string const &err,
mode_t mode = 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.
- int waitForChild() 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.
PRIVATE (VIRTUAL) MEMBER FUNCTIONS
- virtual void childProcess() = 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++.
- virtual void childRedirections():
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.
- virtual void parentProcess() = 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.
- virtual void parentRedirections():
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.
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
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).
BUGS
None Reported.
BOBCAT PROJECT FILES
- https://fbb-git.gitlab.io/bobcat/: gitlab project page;
- bobcat_6.04.00-x.dsc: detached signature;
- bobcat_6.04.00-x.tar.gz: source archive;
- bobcat_6.04.00-x_i386.changes: change log;
- libbobcat1_6.04.00-x_*.deb: debian package containing the
libraries;
- libbobcat1-dev_6.04.00-x_*.deb: debian package containing the
libraries, headers and manual pages;
BOBCAT
Bobcat is an acronym of `Brokken's Own Base Classes And Templates'.
COPYRIGHT
This is free software, distributed under the terms of the
GNU General Public License (GPL).
AUTHOR
Frank B. Brokken (f.b.brokken@rug.nl).