Solved

exec(2) commands returning  to calling program

Posted on 1998-10-07
13
304 Views
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 SECTION_TITLE_MARKER    '['
#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)
    {
        perror("MakeSystemCall");
        return (FALSE);
    }

    strcpy(System_Call_Path,Path_To_System_Call);
    strcat(System_Call_Path,System_Call_Script);

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

    if ( pid <= -1)
    {
        perror(pFullCmd);
    }
    else
    {
        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]); }
            fflush(stdout);
        }
        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 );
        _exit(1);
    }

    if(mutex_unlock(&gSystemCallMutex) != 0)
    {
        perror("MakeSystemCall");
        return(FALSE);
    }
 
    return (rc == 0) ? TRUE : FALSE;
}
0
Comment
Question by:xx4525
[X]
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
13 Comments
 

Author Comment

by:xx4525
ID: 2007288
Edited text of question
0
 

Author Comment

by:xx4525
ID: 2007289
Edited text of question
0
 
LVL 3

Accepted Solution

by:
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.
 
0
Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

 
LVL 3

Expert Comment

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

Expert Comment

by:ozo
ID: 2007292
You may want to fork then exec
0
 
LVL 3

Expert Comment

by:elfie
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.
0
 

Author Comment

by:xx4525
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"?
0
 
LVL 3

Expert Comment

by:arunm
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.
 
0
 
LVL 3

Expert Comment

by:elfie
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()));
#else
  fork_code = fork();
  switch (fork_code)
    {
    case -1:
      Error("Fork failed: %s\n", strerror(own_errno()));
      exit(EXITCODE_LAUNCH_ERROR);

    case 0:             /* the son process */
      close_anything_thats_open();
      setsid();
      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 */
0
 

Author Comment

by:xx4525
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
well?
            default:
                    waitpid(pid, &rc, 0);
                    break;
    }

0
 
LVL 3

Expert Comment

by:arunm
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.
 
 
0
 
LVL 3

Expert Comment

by:elfie
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.
0
 

Author Comment

by:xx4525
ID: 2007300
Cool Thanks all

0

Featured Post

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!

Question has a verified solution.

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

Preface This article introduces an authentication and authorization system for a website.  It is understood by the author and the project contributors that there is no such thing as a "one size fits all" system.  That being said, there is a certa…
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…
This video shows how to set up a shell script to accept a positional parameter when called, pass that to a SQL script, accept the output from the statement back and then manipulate it in the Shell.
In a previous video, we went over how to export a DynamoDB table into Amazon S3.  In this video, we show how to load the export from S3 into a DynamoDB table.
Suggested Courses

632 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