Thursday, September 15, 2022

[FIXED] How to terminate child process when another child process finishes?

Issue

I have a code segment that looks like this:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  pid_t first, last;

  last = fork();
  if (last == 0) {
    char *args[] = { "./last", NULL };
    char *env[] = { NULL };
    execve("./last", args, env);
    _exit(1);
  } else if (last == -1) {
    fprintf(stderr, "Error: failed to fork last.\n");
    exit(1);
  }

  first = fork();
  if (first == -1) {
    fprintf(stderr, "Error: failed to fork first.\n");
    exit(1);
  } else if (first > 0) {
    int status;
    waitpid(first, &status, 0);
  } else {
    char *args[] = { "./first", NULL };
    char *env[] = { NULL };
    execve("./first", args, env);
    _exit(1);
  }

  return 0;
}

This works fine in a sense that I can see processes being invoked and running. However, my issue is that process last has an infinity loop, and when process first terminates, it still stays running. Is there a way in C to force process last here to terminate also when process first finishes?


Solution

kill() should be of interest. From the man page of kill():

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

int kill(pid_t pid, int sig);

Since fork() returns the child PID in the parent, you can use that to call kill(). Here is the modified code and test run.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>  // Modification 1

int main(int argc, char *argv[]) {
  pid_t first, last;

  last = fork();
  if (last == 0) {
    char *args[] = { "./last", NULL };
    char *env[] = { NULL };
    execve("./last", args, env);
    _exit(1);
  } else if (last == -1) {
    fprintf(stderr, "Error: failed to fork last.\n");
    exit(1);
  }

  first = fork();
  if (first == -1) {
    fprintf(stderr, "Error: failed to fork first.\n");
    exit(1);
  } else if (first > 0) {
    int status;
    waitpid(first, &status, 0);
    kill(last, SIGINT);   // Modification 2
  } else {
    char *args[] = { "./first", NULL };
    char *env[] = { NULL };
    execve("./first", args, env);
    _exit(1);
  }

  return 0;
}

Terminal Session (before):

$ ls test first last 
first  last  test
$ ./test
$ ps aux | grep last
root      165130  0.0  0.0   2136   752 pts/3    S    16:58   0:00 ./last
root      165135  0.0  0.0   6136   892 pts/3    S+   16:58   0:00 grep last

Terminal Session (after):

$ ls test first last 
first  last  test
$ ./test
$ ps aux | grep last
root      165240  0.0  0.0   6136   836 pts/3    S+   17:01   0:00 grep last

Regarding which signal to be passed: anyone whose default action is termination. You can find more from the signal man page. Since I don't know what is exactly in the last executable, I assume that there is no signal handler registered for SIGINT and hence when last gets SIGINT, the program is terminated by default.



Answered By - m0hithreddy
Answer Checked By - Marie Seifert (PHPFixing Admin)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.