exec(2) commands returning  to calling program

Posted on 1998-10-07
Last Modified: 2013-12-27
Alright we have multi threaded program that used to
use System calls but appearently the system command
is not thread safe (anymore).  Sun tech support offer
the advice that we should use exec commands instead which
is fine but I cannot get the perl script (or any other script) to return to the calling code.  (see below)
so I can see the debug statment before execvp but not the
printf statement afterwards.  If I can't make the call
this way how can I make the call?

#include "ToolLib.h"
#include <stdlib.h>
#include <libgen.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#define ONE_DAY 1 * 24 * 60 * 60              /* day * hours/day * min/hour * sec/min = 86400 */
#define COMMENT_MARKER          ';'
#define EMPTY_LINE              '\0'

mutex_t gSystemCallMutex;

int main(int argc, char** argv)
    char          gLogDir[DIR_SZ];
    bool          gbDebug;
    char          cmd[CMD_SZ];
    gbDebug = TRUE;
    sprintf(gLogDir, "/home/xx4525/c++/dev/SafeBuild/tgt/unix/log/build/%s");
    sprintf(cmd, "mkdir -p %s ; chmod 777 %s", gLogDir, gLogDir);
    return MakeSystemCall(gbDebug, cmd);

extern bool MakeSystemCall(bool bDebug, char* pFullCmd)
    int     rc;
    pid_t   pid;
    int     i;
    int     arg_list_length;
    char    *FullPath;
    char    System_Call_Path[256];
    char    *Ptr;

    char    msg[256];
    char    *arg_list[16];
    char    Path_To_System_Call[] = "/home/xx4525/perl/dev/";
    char    System_Call_Script[]  = "Plague";

    pid = fork1();

    if (bDebug == TRUE) { printf("\n\tCOMMAND: %s\n\n",pFullCmd ); }
    if(mutex_lock(&gSystemCallMutex) != 0)
        return (FALSE);


    if (bDebug == TRUE) { printf("\n\tSYSTEM SCRIPT: %s\n\n",System_Call_Path ); }

    if ( pid <= -1)
        arg_list[1] = strtok(pFullCmd, " ");
        for(i = 2; (arg_list[i] = strtok(NULL, " ")) != NULL; i++);
        arg_list[i] = NULL;

        if (bDebug == TRUE)
            for(i = 1; arg_list[i] != NULL; i++) { fprintf(stdout, "*** CURRENT COMMAND %d: [%s] ***\n",i, arg_list[i]); }
        rc = execvp(System_Call_Path, arg_list);

        sprintf(msg, "\n\n Don't Thread on me - Cmd: %s\n\n", pFullCmd);
        fprintf( stdout, "%s",msg );

    if(mutex_unlock(&gSystemCallMutex) != 0)
    return (rc == 0) ? TRUE : FALSE;
Question by:xx4525
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 3
  • +1

Author Comment

ID: 2007288
Edited text of question

Author Comment

ID: 2007289
Edited text of question

Accepted Solution

arunm earned 100 total points
ID: 2007290
If a program sucessfully execs, the address space is modifed so there is nothing to return to. The printf will only be reached if the exec fails.
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


Expert Comment

ID: 2007291
Also you dont appear to be distinguishing between the 2 threads in your program. Is this intentional?
LVL 84

Expert Comment

ID: 2007292
You may want to fork then exec

Expert Comment

ID: 2007293
Some more clarification about ozo's comment.

a fork call will duplicate your process into two (almost) identical processes. Then in one of both (normally) the program which get a zero return form the fork call, you will executed the  exec call to replace to current running code with your ocde of choice.
The other process will receive a non-zero return from fork (meaning the son's process id).

As what the system command is , the normal implmentation is first a fork call followed by some form of exec call.

Author Comment

ID: 2007294
Thank you all for your help but I am afraid that I am
going to need some clarification.

Alright I can understand why the printf is not executing but
I should be executing the execvp inside the forked process,
right?  Thus the parent process should complete the execution
after the child is toast or I am executing the execvp on both
the child and the parent?

What do you mean by "distinguishing between the 2 threads"?

Expert Comment

ID: 2007295
After the fork, if the pid = 0, its the child. If the pid > 0 its the parent , a -ve pid indicates a failure. So both your processes are exec-ing.

Expert Comment

ID: 2007296
some sample code for using fork/exec to execute a shell script

  argv[0] = argv0;
  argv[1] = script_file;
  argv[2] = NULL;

#ifdef PROTO_OS2
  script_pid = _spawnvp(P_NOWAIT, "cmd.exe", argv);
  if (script_pid == -1)
    Error("Execvp failed: %s\n",strerror(own_errno()));
  fork_code = fork();
  switch (fork_code)
    case -1:
      Error("Fork failed: %s\n", strerror(own_errno()));

    case 0:             /* the son process */
      Error("Starting background script %s",script_file);
      exec_code = execvp("sh", argv);
      if (exec_code == -1)
      Error("Execvp failed: %s\n", strerror(own_errno()));
      exit(0);/*no EXITCODE necessary here - different process*/
    default:   /* the father must wait until the son is there */
      script_pid = fork_code;      /* to kill afterwards */
#endif /* PROTO_OS2 */
#endif /* MSC32 */

Author Comment

ID: 2007297
Happiness is truely mine I have some more questions but
I think I have a start.  But the questions are for
my knowledge

What do setsid() do for me?  Is is necessary?

I am assuming that close_anything_thats_open() is a user defined
function but what am I looking to close?

Finally I hope
default:   /* the father must wait until the son is there */
             script_pid = fork_code; /* to kill afterwards */
What is the perpose of this commparison and will this work as
                    waitpid(pid, &rc, 0);


Expert Comment

ID: 2007298
Whenever you fork a process, as the child is and exact copy of the parent they will both share items such as file pointers. To avoid a confusion and to aid clairity it is best to close anything that is left open.  Wait is essentially used to syncronise processes, so you can confirm that the child process has finished before continuing with the parent. setsid() is used to process and session group id. In this case it is not mandatory.

Expert Comment

ID: 2007299
setsid() combined with closing stdin/out/err is use dto detach from curent running terminal. it is only needed to make a real deamon process that, after completely started, will show pid 1 as it's parent process. It also prevents that the process will be killed automatically when a user who started it will logoff. (in your case not needed, but i did a cut/paste from some existing code.

The same for close_anything ... Since your starting another program you (probably) don't need any open file from the orignating program. Since Fork duplicates the process, it also duplicates all open filedescriptors, and keeping them open (even when not needed).

The saving of the son's id , is that the parent process will write this id into a file, so later we can do a kill `cat file` to kill the deamon process.

Basically the example is bit to extended, but it shows you the basics of how fork/exec can be used.

Author Comment

ID: 2007300
Cool Thanks all


Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Every server (virtual or physical) needs a console: and the console can be provided through hardware directly connected, software for remote connections, local connections, through a KVM, etc. This document explains the different types of consol…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
HTML5 has deprecated a few of the older ways of showing media as well as offering up a new way to create games and animations. Audio, video, and canvas are just a few of the adjustments made between XHTML and HTML5. As we learned in our last micr…
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).

756 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question