Home Corporate Contacts

TETware Knowledgebase


Products
Solutions

Information

Datasheet
Documentation
FAQ
Knowledgebase

Return to Knowledgebase Index

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.


 


Home Contacts Legal Copyright Corporate News

Copyright © The Open Group 1995-2012, All Rights Reserved