Using C to send an exec process to the background?

17,392

Q: How do I send a process to the background?

A: In general, exactly what you're already doing: fork()/exec().

Q: What's not working as you expect?

I suspect maybe you also want a "nohup" (to completely disassociate the child from the parent).

The key to doing this is to run "setsid()" in the child process:

Share:
17,392
Niklas Rosencrantz
Author by

Niklas Rosencrantz

I'm as simple as possible but not any simpler.

Updated on June 04, 2022

Comments

  • Niklas Rosencrantz
    Niklas Rosencrantz almost 2 years

    My question sounds the same as this but it isn't:

    Start a process in the background in Linux with C

    I know how to do fork() but not how to send a process to the background. My program should work like a simple command unix shell that supports pipes and background processes. I could do pipe and fork but I don't know how to send a process to the background with & like the last line of the program:

    ~>./a.out uname
    SunOS
    ^C
    my:~>./a.out uname &
    

    How to achieve the background process?

    #include <sys/types.h>
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    
    #define TIMEOUT (20)
    
    int main(int argc, char *argv[])
    {
      pid_t pid;
    
      if(argc > 1 && strncmp(argv[1], "-help", strlen(argv[1])) == 0)
        {
          fprintf(stderr, "Usage: Prog [CommandLineArgs]\n\nRunSafe takes as arguments:\nthe program to be run (Prog) and its command line arguments (CommandLineArgs) (if any)\n\nRunSafe will execute Prog with its command line arguments and\nterminate it and any remaining childprocesses after %d seconds\n", TIMEOUT);
          exit(0);
        }
    
      if((pid = fork()) == 0)        /* Fork off child */
        {
          execvp(argv[1], argv+1);
          fprintf(stderr,"Failed to execute: %s\n",argv[1]);
          perror("Reason");
          kill(getppid(),SIGKILL);   /* kill waiting parent */
          exit(errno);               /* execvp failed, no child - exit immediately */
        }
      else if(pid != -1)
        {
          sleep(TIMEOUT);
          if(kill(0,0) == 0)         /* are there processes left? */
        {
          fprintf(stderr,"\Attempting to kill remaining (child) processes\n");
          kill(0, SIGKILL);      /* send SIGKILL to all child processes */
        }
        }
      else
        {
          fprintf(stderr,"Failed to fork off child process\n");
          perror("Reason");
        }
    }
    

    The solution in plain English appears to be here: How do I exec() a process in the background in C?

    Catch SIGCHLD and in the the handler, call wait().

    Am I on the right track?