2

In my parent process, I have created a child process which executes system("find / -print"). From inside the parent, when I try to kill this child process using kill(childProcPID, SIGTERM), it doesn't get terminated immediately. system command keeps on printing the output on console.

Here is the example code:

int main(void) {

    pid_t childProc = fork();
    switch (childProc) {
    case -1:
        perror("fork() error");
        exit(EXIT_FAILURE);
    case 0:
        system("find / -print");
        printf("if I use kill(pid, SIGTERM) control doesnt reach here");
        exit(EXIT_SUCCESS);
    default:
        ;
        int i = 500000;

        //No a great way to put sleep
        //but its just temp
        while (i != 0) {
            --i;
        }

        kill(childProc, SIGTERM);
        break;
    }

    printf("Exit!!!!!!");
    return EXIT_SUCCESS;
}

Please let me know what I am doing wrong or is the right way to kill a child ?

Vinit Sharma
  • 461
  • 2
  • 8
  • 16

3 Answers3

4

The system function will itself create a child process to execute the command (and then block until that child process terminates). What you've done is kill the child process that calls system, but not the child process that system has spawned.

someguy
  • 7,144
  • 12
  • 43
  • 57
  • Are you sure that signal isn't escalated back to the parent process? In other words, does system use setsid() to render a new process session? – Till Apr 17 '14 at 21:35
  • 1
    But anyways, this hints that instead of using `system` you should be using `exec`. – Till Apr 17 '14 at 21:36
  • I also felt that system creates its own child thread. May be I should use exec family functions – Vinit Sharma Apr 17 '14 at 21:38
  • BTW is there anything I can do in current case or should I move to exec ? – Vinit Sharma Apr 17 '14 at 21:39
  • 1
    @Vinit Sharma: If you want to have control over whether to kill the process prematurely, you can't use `system`. You have to use one of the `exec` functions. – someguy Apr 17 '14 at 21:42
  • but one more doubt..how can you execute a user typed command using exec functions..they all accepts the path arguments but In my code, I want to run different commands (kind of like a shell) – Vinit Sharma Apr 17 '14 at 21:45
  • 2
    @Vinit Sharma: Shell commands such as `cd` won't work, but actual programs will. Note that `execlp` and `execvp` accept filenames (so it accepts `find` rather than `/usr/bin/find`). The paths it searches depends on *your* program's environment variables. – someguy Apr 17 '14 at 21:53
  • maha's solution also worked...but I may consider this as well – Vinit Sharma Apr 17 '14 at 22:35
2

try setting the session id and killing the process group instead (man 2 kill)

int main(void) {

pid_t childProc = fork();
switch (childProc) {
case -1:
    perror("fork() error");
    exit(EXIT_FAILURE);
case 0:
    setsid();
    system("find / -print" );
    printf("if I use kill(pid, SIGTERM) control doesnt reach here");
    exit(EXIT_SUCCESS);
default:
    sleep(1);
    kill(childProc*-1, SIGTERM);
    break;
}

printf("Exit!!!!!!");
return EXIT_SUCCESS;
}

this more or less works. The caveat is that there's a bit of a race in that the parent has to give the child time to setsid(), hence the sleep.

Hope that helps.

maha
  • 605
  • 6
  • 13
  • Yes, It did work...but I am just wondering is it going to cause any additional problem in any case ? – Vinit Sharma Apr 17 '14 at 22:29
  • 1
    @Vinit Sharma: There's no problem with this solution. All I'll say is you shouldn't rely on `sleep` to avoid a race condition, but in this case, it doesn't really matter how soon `kill` is called. However, is it not more elegant to use the `exec` functions? Here, you're creating a new session just so you can kill the processes as a group. – someguy Apr 17 '14 at 22:42
  • 1
    @Vinit Sharma. You'll have no additional problems with it. It will only kill the processes in the process group. You should however feel free to experiment with the exec functions as well. However you may find that depending on what you invoke with them you may still need to setsid() in order to ensure propagation to any subsequent tertiary children that may be spawned. – maha Apr 17 '14 at 22:59
  • @someguy: thanks..I am not using sleep function in my actual code...it made this program so that I will not have to copy paste the exact code. I am experimenting with the exec functions as well. thanks a lot for your inputs. – Vinit Sharma Apr 17 '14 at 23:31
1

First, you should be checking the result that you get back from kill() -- if you get 0 back, the operation succeeded. If you get -1 back, though, check the global variable errno to see what the problem was.

If the signal is being sent successfully, the only thing you can do is make sure that you're sending the signal that you intend. As @Till points out in a comment, sending SIGKILL instead of SIGTERM will be more effective because the OS handles the former and the target process cannot ignore it.

In any case, realize that interacting with other processes is usually an asynchronous process -- the target process probably won't be terminated by the time kill() returns no matter what you do.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • Thanks for your help but it just made this program up to show my problem..I know I should use the return value of kill and I agree with your last point. – Vinit Sharma Apr 17 '14 at 21:37