Killing process that has been created with popen2

后端 未结 2 1256
北海茫月
北海茫月 2021-01-16 16:26

I\'m using the function popen2 (that has been recommended elsewhere on stackoverflow) to programatically create a process that has to be killed again after some time. popen2

相关标签:
2条回答
  • 2021-01-16 16:54

    I think I got it.

    execl("/bin/sh", "sh", "-c", command, NULL);
    

    runs sh and popen2 returns it's pid. When you call kill it kills sh, but does not touch it's child process command. It is actually a fluke that killing the next pid kills command. This will not always work and is just up to race conditions.

    If you want to be able to kill your target process then you will have to start that directly.

    Warning (untested code):

    pid_t popen2(const char **command, int *infp, int *outfp) {
    
        int p_stdin[2], p_stdout[2];
        pid_t pid;
    
        if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
            return -1;
    
        pid = fork();
    
        if (pid < 0)
            return pid;
        else if (pid == 0)
        {
            close(p_stdin[WRITE]);
            dup2(p_stdin[READ], READ);
            close(p_stdout[READ]);
            dup2(p_stdout[WRITE], WRITE);
    
            execvp(*command, command);
            perror("execvp");
            exit(1);
        }
    
        if (infp == NULL)
            close(p_stdin[WRITE]);
        else
            *infp = p_stdin[WRITE];
    
        if (outfp == NULL)
            close(p_stdout[READ]);
        else
            *outfp = p_stdout[READ];
    
        return pid;
    }
    

    and pass command in the form of

    char *command[] = {"program", "arg1", "arg2", ..., NULL};
    

    in your particular example:

    char *command[] = {"crafty", NULL};
    
    0 讨论(0)
  • 2021-01-16 16:55

    You can use 'exec' command of shell to avoid pending process. Also: popen2 shall close the writing end of unused pipes, otherwise the pipe remains open. If one of pointers (infp, outpf) is NULL, it is useless to create and immediately close the pipe. Here is the version of popen2 I use in my project:

    pid_t popen2(char *command, int *in_fd, int *out_fd) {
        int     pin[2], pout[2];
        pid_t   pid;
        char    cmd[strlen(command)+10];
    
        if (out_fd != NULL) {
            if (pipe(pin) != 0) return(-1);
        }
        if (in_fd != NULL) {
            if (pipe(pout) != 0) {
                if (out_fd != NULL) {
                    close(pin[0]);
                    close(pin[1]);
                }
                return(-1);
            }
        }
    
        pid = fork();
    
        if (pid < 0) {
            if (out_fd != NULL) {
                close(pin[0]);
                close(pin[1]);
            }
            if (in_fd != NULL) {
                close(pout[0]);
                close(pout[1]);
            }
            return pid;
        }
        if (pid==0) {
            if (out_fd != NULL) {
                close(pin[1]);
                dup2(pin[0], 0);
            }
            if (in_fd != NULL) {
                close(pout[0]);
                dup2(pout[1], 1);
            }
            // Exec makes possible to kill this process 
            sprintf(cmd, "exec %s", command);
            execlp("sh", "sh", "-c", cmd, NULL);
            fprintf(stderr, "%s:%d: Exec failed in popen2. ", __FILE__, __LINE__);
            perror("Error:");
            exit(1);
        }
        if (in_fd != NULL) {
            close(pout[1]);
            *in_fd = pout[0];
        }
        if (out_fd != NULL) {
            close(pin[0]);
            *out_fd = pin[1];
        }
        return pid;
    }
    
    0 讨论(0)
提交回复
热议问题