fork






FBB::Fork − Implements fork(2) using the Template Design
Pattern


#include <bobcat/fork>
Linking option: −lbobcat


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:

o    int WIFEXITED(int status):
     This macro returns a nonzero value if the child process
     terminated normally with ‘exit’ or ‘_exit’.

o    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.

o    int WIFSIGNALED(int status):
     This macro returns a nonzero value if the child process
     terminated because it received a signal that was not
     handled.

o    int WTERMSIG(int status):
     If ‘WIFSIGNALED’ is true of ‘status’, this macro
     returns the signal number of the signal that terminated
     the child process.

o    int WCOREDUMP(int status):
     This macro returns a nonzero value if the child process
     terminated and produced a core dump.

o    int WIFSTOPPED(int status):
     This macro returns a nonzero value if the child process
     is stopped.

o    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.










                             ‐2‐


FBB
All constructors, members, operators and manipulators,
mentioned in this man−page, are defined in the namespace
FBB.








     Only the default constructor is available.  )




o    virtual ~Fork():
     Derived classes may define their own destructor, which
     is called when the Fork destructor is activated.





o    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.





o    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++.

o    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.










                             ‐3‐


o    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.

o    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.

o    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). Note
     that the value of pid is undefined when called before
     the member fork has been called.

o    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.

o    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.

o    int waitForChild():
     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









                             ‐4‐


     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.




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










                             ‐5‐


     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









                             ‐6‐


    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;
}




bobcat/fork − defines the class interface


bobcat(7), cerrextractor(3bobcat), cininserter(3bobcat),
coutextractor(3bobcat), exec(3bobcat), fork(2),
pipe(3bobcat), redirector(3bobcat), stdextractor(3bobcat),
wait(2), waitpid(2).













                             ‐7‐


None Reported.




o    bobcat_5.02.00−x.dsc: detached signature;

o    bobcat_5.02.00−x.tar.gz: source archive;

o    bobcat_5.02.00−x_i386.changes: change log;

o    libbobcat1_5.02.00−x_*.deb: debian package holding the
     libraries;

o    libbobcat1−dev_5.02.00−x_*.deb: debian package holding
     the libraries, headers and manual pages;

o    http://sourceforge.net/projects/bobcat: public archive
     location;



Bobcat is an acronym of ‘Brokken’s Own Base Classes And
Templates’.


This is free software, distributed under the terms of the
GNU General Public License (GPL).


Frank B. Brokken (f.b.brokken@rug.nl).