I wrote a little program using fork to create new processes which use pipes to communicate. Applying defensive programming, I check every return value. If a return value indicates that something went wrong, I want to free all resources, close all pipes and the parent process to wait on it’s child processes to terminate. Now, what’s the best way to bail out if an error occurs?
At the moment, I’m doing it this way:
/* initialize pipes */
if(pipe(p1fd) == -1) {
(void) printError("Could not init pipe 1");
exit(EXIT_FAILURE);
}
if(pipe(p2fd) == -1) {
(void) printError("Could not init pipe 2");
(void) close(p1fd[0]);
(void) close(p1fd[1]);
exit(EXIT_FAILURE);
}
switch (pid = fork()) {
case -1:
(void) printError("Could not fork");
(void) close(p1fd[0]);
(void) close(p1fd[1]);
(void) close(p2fd[0]);
(void) close(p2fd[1]);
exit(EXIT_FAILURE);
break;
case 0: /* child process */
break;
default: /* parent process */
break;
}
This gets quite cumbersome if one needs more resources. Another way I thought of was providing a bailout function that simply closes all pipes without caring if the pipes have actually been opened (same for freeing memory and calling wait on child processes). But then, all variables needed in such a bail out function would have to be global, since some of the pipes are passed on to different child processes/functions.
You could use
gototo avoid repeating the same code in each of the failure branches: