Cyborg-X1
Cyborg-X1

Reputation: 373

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.

Upvotes: 1

Views: 1531

Answers (2)

Serge Ballesta
Serge Ballesta

Reputation: 148890

NEVER USE execv functions in threads because the execve() system call overlays the current process image with a new process image.

The correct pattern if fork-exec or better vfork-exec. Extract from the manpage:

The vfork() system call can be used to create new processes without fully copying the address space of the old process, which is horrendously inefficient in a paged environment. It is useful when the purpose of fork(2) would have been to create a new system context for an execve(2). The vfork() system call differs from fork(2) in that the child borrows the parent's memory and thread of control until a call to execve(2) or an exit (either by a call to _exit(2) or abnormally). The parent process is suspended while the child is using its resources.

Using vfork shortly followed with execve, you avoid the copy of the original process image, and do not erase if with the new process, so the original process has the pid of its child and cat control it, look whether it has ended, send it signals and so on.

Upvotes: 3

anonymous coward
anonymous coward

Reputation: 144

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).

Upvotes: 3

Related Questions