Information
|
20.
How to create multiple processes using tet_fork()
This information is not applicable to Win32 systems.
Question
I have a need to fork multiple process.
After forking multiple processes, the parent should wait for all these
processes.
Typically my code should like this:
for (i = 0; i < 10; i++) {
if ((pid = fork()) == 0)
child_func();
}
for (i = 0; i < 10; i++) {
waitpid(.......);
/* check for the child's return status... */
}
. . .
If I use
fork()
I am not able to use API functions in the child processes.
If I use
tet_fork()
I cannot create more than one child process at once.
Is there any way to do this?
Answer
You can do this using recursive calls to a
(*parentproc)()
function.
For example:
#include <stdlib.h>
#include <tet_api.h>
void (*tet_startup)() = TET_NULLFP, (*tet_cleanup)() = TET_NULLFP;
static void tp1(), tp1_child(), tp1_parent();
struct tet_testlist tet_testlist[] = {
{ tp1, 1 },
{ TET_NULLFP, 0 }
};
static int tp1_fcount;
static int testfail;
static void tp1()
{
testfail = 0;
tp1_fcount = 0;
tp1_parent();
if (!testfail)
tet_result(TET_PASS);
}
static void tp1_parent()
{
int level;
void (*parentproc)();
if ((level = ++tp1_fcount) < 10)
parentproc = tp1_parent;
else
parentproc = TET_NULLFP;
(void) tet_printf("about to call tet_fork(): level = %d", level);
if (tet_fork(tp1_child, parentproc, 30, 0) < 0) {
/* API prints an infoline and generates a result */
testfail++;
}
else
(void) tet_printf("tet_fork() succeeded, level = %d", level);
}
static void tp1_child()
{
(void) tet_printf("in child process, PID = %d", getpid());
tet_exit(0);
}
Question
How to I extend this example to an arbitrary number of child processes
without creating an infinite number of stack frames?
Answer
This is a rather different situation.
You can call
tet_fork()
with a waittime of -1.
In this case, the API does not wait for the child process and the
validresults
argument is ignored.
When this feature is used, the
parentproc
function is supposed to wait for the child.
If the child is still running when the
parentproc
function returns, the
API kills the child process.
So you have to fool the API by providing a dummy child for it to kill;
that way your child process is still running when
tet_fork()
returns.
The dummy child process must not call any API functions.
Then it is your responsibility to make sure that you have waited for
all the child processes to exit before the test purpose returns control
to the TCM.
For example:
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <tet_api.h>
void (*tet_startup)() = TET_NULLFP, (*tet_cleanup)() = TET_NULLFP;
static void tp1(), tp1_child(), tp1_parent();
struct tet_testlist tet_testlist[] = {
{ tp1, 1 },
{ TET_NULLFP, 0 }
};
static int testfail;
static pid_t child_pid;
void tp1()
{
testfail = 0;
for (;;) {
/*
** you will need some code here to wait for some event
** and/or break out of the loop
*/
tet_infoline("parent: about to call tet_fork()");
if (tet_fork(tp1_child, tp1_parent, -1, 0) < 0) {
/* API prints a diagnostic */
testfail++;
break;
}
(void) tet_printf("parent: child PID = %d", child_pid);
}
/*
** you must ensure that all the child processes have exited
** at this point
*/
if (!testfail)
tet_result(TET_PASS);
}
static void tp1_parent()
{
int pid;
/* create a dummy child for the API to kill */
switch (pid = fork()) {
case 0:
/* child must not call any API functions */
(void) signal(SIGTERM, SIG_DFL);
pause();
_exit(0);
break;
case -1:
/* real trouble here - the only safe thing to do is to
exit from the test case */
(void) tet_printf("fork() failed, errno = %d", errno);
tet_exit(1);
}
/* arrange for the API to kill the dummy child instead of the
childproc function */
child_pid = tet_child;
tet_child = pid;
return;
}
static void tp1_child()
{
(void) tet_printf("in child process, PID = %d", getpid());
/* whatever you want here */
tet_exit(0);
}
Not that this example does not contain any code to wait for the child
processes, or to cause the main loop to end.
So if you compile and run the code as it stands, you will run out of
processes at some point.
See also
-
"Generating and executing processes'' in Chapter 8 of the
TETware Programmers Guide.
|