1

I have a main that runs program from the command line arguments. The command line program is forked and run in the child process. When SIGINT is sent, I want to catch it and ask the user to confirm that he/she want to quit. If yes, both parent and child end, else child keeps running. My problem is that I can't get the child to start running back up, when user says no. I have tried SIGSTOP & SIGCONT but these actually just cause the processes to stop.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>

extern char **environ;
void sigint_handler(int sig);
void sigint_chldhandler(int sig);

int main( int argc, char** argv)
{
    int pid;
    signal(SIGINT,sigint_handler);


    if((pid=fork())==0)
    {
            printf("%d\n",pid);

            execve(argv[1],argv,environ);
    }


    int status;
    waitpid(pid,&status,0);
}
void sigint_handler(int sig)
{
    printf("Do you want to quit?Yes/No:\n");
    char buf[4];
    fgets(buf, sizeof(char)*4, stdin);

    printf("child pid:%d\n",getpid());
    printf("parent pid:%d\n",getppid());

    if(strcmp(buf,"Yes")==0)
    {
            kill(-getpid(),SIGKILL);
            printf("Exiting!\n");
            exit(0);
    }

}
user3213348
  • 255
  • 1
  • 5
  • 14
  • 1
    http://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint - is it? – someuser Feb 26 '14 at 02:51
  • Also you can use `signal(SIGINT, SIG_IGN);` in child process, I think, or write another SIGINT handler for it. – someuser Feb 26 '14 at 02:54
  • no if I block sigint then the infite child process is never stopped when the user presses ctrl C. I want to send cntl C sig and ask the user to confirm if he really wants to quit, if the user says no then the child process continues – user3213348 Feb 26 '14 at 03:00
  • You can stop child from parent process. You have a child pid. SIGINT comes to parent process and to child process. Parent process calls your handler. Child processes this signal by default. This is your problem. – someuser Feb 26 '14 at 03:07

2 Answers2

2

Unless you rig the child's signal handling, it will be terminated by the interrupt when the signal is sent, regardless of what happens in the parent. Therefore, you will need to be rather more sophisticated. I think you will need something along the lines of:

  1. Parent process sets its SIGINT signal handler.
  2. Parent forks.
  3. Child process sets its SIGINT handling to SIG_IGN.
  4. Child executes specified command.
  5. Parent waits for SIGINT to arrive, probably while running waitpid().
  6. When it arrives, it sends SIGSTOP to the child.
  7. It asks the question and gets the response.
  8. If the response is to continue, then it sends SIGCONT to the child and returns to its waiting mode.
  9. If the response is to stop, then it sends first SIGCONT and then SIGTERM (or another signal other than SIGINT) to the child to kill it. (Using SIGKILL is not sensible; the child should be given a chance to exit in response to SIGTERM or SIGHUP. If the child doesn't take the death threat seriously, then you can send it SIGKILL.)
  10. When the parent has established that the child has exited, it can exit in its own turn.

Note that if the child process is running something like vim, which alters the terminal settings dramatically, then sending it SIGKILL will leave the terminal in a cockeyed state. It is fiddly setting it back to a sane state; it is better to give the program a chance to reset the terminal settings in its own right.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

SIGINT comes to parent process and to child process (to process group).
Parent process calls your handler.
Child processes this signal by default.
You can use this, for example:

#include <unistd.h>
#include <signal.h>
#include <stdio.h>
int main()
{
    pid_t pid;
    char c;
    switch(pid = fork())
    {
        case -1:
            printf("!!!");
            return -1;
        break;
        case 0:
            printf("child started\n");
            while(1) { };
        break;
        default:
            while(1)
            {
                c = getchar();
                if(c == 'q')
                {       
                        //your conditions
                        kill(pid, SIGKILL);
                        return 0;
                }
            }
        break;
    }
    return 0;
}
someuser
  • 189
  • 1
  • 11