[Clfs-commits] [CLFS Trac] #210: The way to use execvp in the multiarch_wrapper, in order to keep control over the processes.

CLFS Trac trac at cross-lfs.org
Wed May 20 13:33:39 PDT 2009


#210: The way to use execvp in the multiarch_wrapper, in order to keep control
over the processes.
-------------------------------+--------------------------------------------
 Reporter:  manurootcpp        |       Owner:  clfs-commits at lists.cross-lfs.org.
     Type:  task               |      Status:  new                              
 Priority:  minor              |   Milestone:  CLFS Standard 1.2.0              
Component:  BOOK               |     Version:  CLFS Standard 1.2.0              
 Keywords:  multiarch_wrapper  |  
-------------------------------+--------------------------------------------
 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

-- 
Ticket URL: <http://trac.cross-lfs.org/ticket/210>
CLFS Trac <http://trac.cross-lfs.org>
The Cross Linux From Scratch Project.


More information about the Clfs-commits mailing list