Search code examples
c++linuxmultithreadingexecveexternal-application

Dynamically executing and terminating external programs with C++


I need to execute processes with still being in control of each process. I want to create a class which stores the threads or pids or what ever is necessary to do so.

I currently have a program which executes one external application with the C function execvp and also loads the environment from a shell script. So my current program is blocking. But I need to be able to keep it freely running and only by time I terminate a currently running or start a new external application.

My current approach would be to create a thread, which uses the execve function. But then the thread would be blocking as far as I can see.

The code which might be in the thread (with variables then):

char *argv[] = { "/bin/bash", "-c", "myApplication", 0 };
execve(argv[0], &argv[0], environment.data());

The applications called are probably not fixed in the code their names will be given by an external setup file, including parameters.

Now my actual question, is there a better way to "manage" external applications like that in c++? Some ready solution (class, library)? And if not how do I terminate the thread if this is the actual way. Using the terminate call is said to be bad practice, that's what I often read.

I hope this is now specific enough for the forum, because I do not know how to get more specific anymore. If you need more hints what I want to create here, feel free to ask in the comments.

Update:

to DBus & others:

Additional information I do not wrote all of the processes I want to start! So it will be used to start 3rd party applications, which even if I have the code, do not want to change.


Solution

  • You want to fork() before you exec. fork() is a function that creates a new process identical to the original caller of fork() running as a subprocess. The difference is that the parent process gets the child's pid as a return value and the child gets 0. The gist of what you want to do is this:

    pid_t pid = fork();
    
    if( pid == 0 )
    {
        // we're the child process
        char *argv[] = { "/bin/bash", "-c", "myApplication", 0 };
        int rc = execve(argv[0], &argv[0], environment.data());
        // execve only returns if there was an error
        // check 'errno' and handle it here
    }
    else if ( pid < 0 )
    {
        // pid is less than zero, we didn't successfully fork,
        // there is no child process.
        throw "error message";
    }
    
    // do whatever processing the parent does
    

    More info is here. The kill() function isn't bad practice per se, if you want to quickly and gracefully end the subprocess you can write signal handlers in it, but you should be using something like dbus or zeromq to do proper interprocess communication. You want to tell the program to do something, not just tell it to die (usually what you want it to do if you're killing it).