8

When we use system() command, program wait until it complete but I am executing a process using system() and using load balance server due to which program comes to next line just after executing system command. Please note that that process may not be complete.

system("./my_script");

// after this I want to see whether it is complete or not using its pid.
// But how do i Know PID?
IsScriptExecutionComplete();
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
EmptyData
  • 2,386
  • 2
  • 26
  • 42
  • Not sure I understand the load balance server thing. Are you calling something that launches a command on a remote server? – jsantander Apr 02 '14 at 06:31
  • @jsantander we are using `Platform LSF` . this return to main program as soon as we call `system()`. But that process may not be complete. – EmptyData Apr 02 '14 at 06:42
  • I'm afraid I don't have experience in Platform LSF (consider adding that to the tags of your question). But, if I understand it correctly, you're scheduling a job in a remote computing resource. This **remote job** has nothing to do with your **local** process IDs.... So my suggestion is that you look for an API or command within the Platform LSF API that allows you to monitor the state of an scheduled job through the Platform LSF API. – jsantander Apr 02 '14 at 07:03

4 Answers4

9

Simple answer: you can't.

The purpose of system() is to block when command is being executed.

But you can 'cheat' like this:

pid_t system2(const char * command, int * infp, int * outfp)
{
    int p_stdin[2];
    int p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) == -1)
        return -1;

    if (pipe(p_stdout) == -1) {
        close(p_stdin[0]);
        close(p_stdin[1]);
        return -1;
    }

    pid = fork();

    if (pid < 0) {
        close(p_stdin[0]);
        close(p_stdin[1]);
        close(p_stdout[0]);
        close(p_stdout[1]);
        return pid;
    } else if (pid == 0) {
        close(p_stdin[1]);
        dup2(p_stdin[0], 0);
        close(p_stdout[0]);
        dup2(p_stdout[1], 1);
        dup2(::open("/dev/null", O_RDONLY), 2);
        /// Close all other descriptors for the safety sake.
        for (int i = 3; i < 4096; ++i)
            ::close(i);

        setsid();
        execl("/bin/sh", "sh", "-c", command, NULL);
        _exit(1);
    }

    close(p_stdin[0]);
    close(p_stdout[1]);

    if (infp == NULL) {
        close(p_stdin[1]);
    } else {
        *infp = p_stdin[1];
    }

    if (outfp == NULL) {
        close(p_stdout[0]);
    } else {
        *outfp = p_stdout[0];
    }

    return pid;
}

Here you can have not only PID of the process, but also it's STDIN and STDOUT. Have fun!

GreenScape
  • 7,191
  • 2
  • 34
  • 64
  • I think in above function `_exit(1)` would never call because after executing `execl` it return from there.Right? – EmptyData Apr 02 '14 at 08:39
  • @Vinay it may... execl() can fail due to for example insufficient memory. – GreenScape Apr 02 '14 at 08:46
  • No, even if execl would execute successfully even then `_exit(1)` would never call. As `The exec() family of functions replaces the current process image with a new process image` – EmptyData Apr 02 '14 at 08:50
  • You can test it writing `cout` statement below `execl` statement that `cout` would not call. – EmptyData Apr 02 '14 at 08:51
  • @Vinay why you don't consider the case that `execl()` may fail before image is replaced? For example when you are trying to execute text file... – GreenScape Apr 02 '14 at 09:01
  • Yes, that case could occur , I just want to confirm that `_exit(1)` would never call whether `execl()` succeed or fail.I dont know whether I am wrong or right. – EmptyData Apr 02 '14 at 09:03
  • @Vinay, yes you are correct. After image is replaced, it is completely different program then. – GreenScape Apr 02 '14 at 11:50
2

Not an expert on this myself, but if you look at the man page for system:

system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed

You can go into the background within the command/script you're executing (and return immediately), but I don't think there's a specific provision in system for that case.

Ideas I can think of are:

  1. Your command might return the pid through the return code.
  2. Your code might want to look up the name of the command in the active processes (e.g. /proc APIs in unix-like environments).
  3. You might want to launch the command yourself (instead of through a SHELL) using fork/exec
jsantander
  • 4,972
  • 16
  • 27
1

As the other answers said, std::system blocks until complete anyway. However, if you want to run the child process async and you are ok with boost you can use boost.process (ref):

#include <boost/process.hpp>

namespace bp = boost::process;

bp::child c(bp::search_path("echo"), "hello world");

std::cout << c.id() << std::endl;
// ... do something with ID ...

c.wait();
duick
  • 33
  • 1
  • 7
0

You can check exit status of your command by following code :

int ret = system("./my_script");

if (WIFEXITED(ret) && !WEXITSTATUS(ret))
{
    printf("Completed successfully\n"); ///successful 
}
else
{
    printf("execution failed\n"); //error
}
Rahul R Dhobi
  • 5,668
  • 1
  • 29
  • 38
  • 1
    @Rahul If we use load balance server then system command return success even that script execution is not complete .are you getting my point? – EmptyData Apr 02 '14 at 06:27
  • @Vinay: please refer http://stackoverflow.com/questions/8654089/return-value-of-system-in-c – Rahul R Dhobi Apr 02 '14 at 06:40