Opened 16 years ago

Last modified 15 years ago

#210 closed task

The way to use execvp in the multiarch_wrapper, in order to keep control over the processes. — at Version 1

Reported by: manurootcpp Owned by: clfs-commits@…
Priority: minor Milestone: CLFS Standard 1.2.0
Component: BOOK Version: CLFS Standard 1.2.0
Keywords: multiarch_wrapper Cc:

Description (last modified by Joe Ciccone)

As it is explained in the glibc manual, the exec like functions don't keep any trace of the calling process: "Executing a new process image completely changes the contents of memory, copying only the argument and environment strings to new locations."

So when we use execvp without any traitment, the multiarch_wrapper exit when the "filename" program finish. As a result, we never reach the end of program (i.e. perror and free).

To use execvp, we must first create a child process with the fork() function. This child process executes the command (filename), and return normally. The parent process waits this return, and we can finish the job.

This is the modified multiarch_wrapper that i propose :

/* multiarch_wrapper.c for CLFS multilib */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#ifndef USE_ARCH
#define USE_ARCH "64"
#endif

/* Find in libc manual, 26.9.Process creation example. Page 685. */
/* Modified to use execvp instead of execl use in the libc example.*/
/* Execute a program "command", with an array of commands "arg[]" */

int my_system (const char *command, char *const arg[])
{
	int status;
	pid_t pid;
	pid = fork ();
	if (pid == 0)
	{
		/* This is the child process. Execute command with arg[] */
		execvp ( command, arg );
		_exit (EXIT_FAILURE);
	}
	else if (pid < 0)
		/* The fork failed. Report failure. */
		status = -1;
	else
		/* This is the parent process. Wait for the child to complete. */
		if (waitpid (pid, &status, 0) != pid)	/* waitpid return the child pid, status stocks the returned code by child */
			status = -1;
	return status;
}

int main ( int argc, char **argv )
{
	char *filename = NULL;
	char *use_arch = NULL;
	
	if(!(use_arch = getenv("USE_ARCH")))
		use_arch = USE_ARCH;
	
	if (asprintf (&filename, "%s-%s", argv[0], use_arch) < 0)	/* If asprintf fails, return a value < 0, else,
	 									if ok return number of char allocated */
	{
		perror (argv[0]);
		return -1;
	}
	
	if (my_system (filename,argv) == -1)
	{
		perror (argv[0]);
		free (filename);
		return -1;
	}
	
	free (filename);
	
	return 0;
}

It's a longer source, but with this, we keep control over the processes. But in fact, it's a delicate task to execute a child process. Glibc doc precise that the waitpid function is a "cancellation point" in multithreaded programs, but i don't yet know how to solve this potential problem. Since i don't understand what is exactly a "cancellation point".

PS: I'm french, so, exuse me if my ticket isn't in a good english.

This is where can be found the pdf of The GNU C Library Reference Manual: http://www.gnu.org/software/libc/manual/pdf/libc.pdf

Change History (2)

by manurootcpp, 16 years ago

Attachment: multiarch_wrapper.c added

comment:1 by Joe Ciccone, 16 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.