简体   繁体   中英

How to close previously opened shell (C++)

i am opening a shell like this in my C++ code:

int pid = fork()
if (pid==0){
    system("script.sh")
}
[rest of the code]

At the end of my C++ program, I also want to close that opened shell, is that possible?

When script.sh completes, the shell it was running in will terminate on its own, you don't need to "close" it.

However, if the parent process is still running, the child will become a "zombie" (marked with a Z in the output of the ps command). It will remain in this state until the parent either reads its return code or exits itself.

So if [rest of the code] is brief, you may not have to do anything. When the parent exits, the child will be cleaned up by the operating system.

But if [rest of the code] runs for a while, or this code segment is called multiple times, then you want to clean up your zombies so they don't accumulate. This is done with the waitpid() system call.

For example:

int pid = fork()
if (pid==0){
    system("script.sh")
} else {
    int status = 0;
    int result = waitpid(pid, &status, 0);
    if (result == -1) {
        /* error */
    else {
       [rest of the code]
    }
}

Note that the parent process will block in the waitpid() call until the child has finished. If this is not what you want, you can pass the WNOHANG option in place of 0 as the final argument. When it does return, 'status' will contain the return code of your script. You can get more details about it all by reading "man 2 waitpid".

Update (in response to comment that script does not exit on its own):

The cleanest solution in the abstract would probably be to redesign so that the script does exit on its own, but if for whatever reason that is not possible, then the parent can kill the script forcibly using the kill() system call. The code would look something like this:

#include <sys/types.h>
#include <signal.h>

int pid = fork()
if (pid==0){
    system("script.sh")
} else if (pid > 0) {
    /* do whatever in parent*/

    /* Note it is very important to check that fork did not fail */
    /* and return -1, because if you do "kill(-1, SIGTERM)" you */
    /* are in fact sending the TERM signal to **every process** */
    /* on your system. If running as root, this would be A Very Bad */
    /* Thing.  */
    kill(pid, SIGTERM);
} else {
    /* error */
}

kill() can return -1 on error, so if you care a lot about the script not being cleaned up, you can check that. If for instance SIGTERM doesn't kill it, you can escalate to sending SIGKILL (like "kill -9" from the command line):

if (kill(pid, SIGTERM) == -1) {
    kill(pid, SIGKILL);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM