1

Looking to fork a process, in c++, that wont hang its parent process - its parent is a daemon and must remain running. If i wait() on the forked process the forked execl wont defunt - but - it will also hang the app - not waiting fixes the app hang - but the command becomes defunt.

if((pid = fork()) < 0)
    perror("Error with Fork()");
else if(pid > 0) { 
    //wait here will hang the execl in the parent
    //dont wait will defunt the execl command 
    //---- wait(&pid);
    return "";
} else {
    struct rlimit       rl;
    int                 i;

    if (rl.rlim_max == RLIM_INFINITY)
        rl.rlim_max = 1024;

    for (i = 0; (unsigned) i < rl.rlim_max; i++)
        close(i);

    if(execl("/bin/bash", "/bin/bash", "-c", "whoami", (char*) 0) < 0) perror("execl()");
    exit(0);
}

How can I fork the execl without a wait(&pid) where execl's command wont defunct?

UPDATE Fixed by adding the following before the fork

signal(SIGCHLD, SIG_IGN);

Still working with my limited skills at a more compatible solution based on the accepted answer. Thanks!

Will Bowman
  • 407
  • 9
  • 20

4 Answers4

6

By default, wait and friends wait until a process has exited, then reap it. You can call waitpid with the WNOHANG to return immediately if no child has exited.

The defunct/"zombie" process will sit around until you wait on it. So if you run it in the background, you must arrange to reap it eventually by any of several ways:

  • try waitpid with WNOHANG routinely: int pid = waitpid(-1, &status, WNOHANG)
  • install a signal handler for SIGCHLD to be notified when it exits

Additionally, under POSIX.1-2001, you can use sigaction set the SA_NOCLDWAIT on SIGCHLD. Or set its action to SIG_IGN. Older systems (including Linux 2.4.x, but not 2.6.x or 3.x) don't support this.

Check your system manpages, or alternative the wait in the Single Unix Specification. The Single Unix Spec also gives some helpful code examples. SA_NOCLDWAIT is documented in sigaction.

derobert
  • 49,731
  • 15
  • 94
  • 124
  • easiest solution was adding a signal(SIGCHLD, SIG_IGN); before my fork - I tried almost all the other options that seem beyond my limited skills. I'll keep trying just in case people want to use 2.4.x. – Will Bowman Feb 07 '12 at 02:18
0

As said in comment, double fork saves process from defunct state.

What is the reason for performing a double fork when creating a daemon?

Pavel Patrin
  • 1,630
  • 1
  • 19
  • 33
  • This is a borderline [link-only answer](//meta.stackexchange.com/q/8231). You should expand your answer to include as much information here, and use the link only for reference. – Blue Nov 04 '18 at 20:59
0

EX1: When client not exit, no wait

#include <spawn.h>
extern char** environ; //posix_spawn using environ that declare in glibc-2.xx/posix/environ.c
void main()
{
    pid_t   spawnid;
    char    param[64] = {0};
    char*   args[] = {"/usr/drive_server", param, NULL};
    posix_spawn(&spawnid, "/usr/drive_server", NULL, NULL, args, 
    environ);
    getchar();
}

EX2: When client exit, wait subprocess detach

#include <spawn.h>
extern char** environ;
void main()
{
    pid_t   spawnid;
    char    param[64] = {0};
    pid_t   sessionid;
    char*   args[] = {"/usr/drive_server", param, NULL};
    
    posix_spawn(&spawnid, "/usr/drive_server", NULL, NULL, args, environ);
    
    sessionid = 0;
    while( sessionid != spawnid )
    {
        sessionid = getsid(spawnid);
        printf("sessionid id %d\n", sessionid);
        usleep(200000);
    }
}

    //subprocess file
    void main()
    {
        setsid(); //detach
        getchar();
    }

EX3: when system have setsid command, no wait

#include <spawn.h>
extern char** environ;
void main()
{
    pid_t   id_spawn;
    char*   args[] = {"/usr/bin/setsid", "/volume1/drive_server", serviceName8, NULL};

    posix_spawn(&id_spawn, "/usr/bin/setsid", NULL, NULL, args, environ);
    printf("drive_server* spawn id %d\n", id_spawn);
}

there are 2 sources code can be referred to

  1. util-linux-2.xx.x/sys-utils/setsid.c
  2. busybox-1.xx.x/util-linux/setsid.c
0

I think a signal handler would be the best way as indicated. I would like to point out another way this could be handled: Fork twice and have the child exit while the grandchild would call execl. The defunct process would then be cleaned up by the init process.

Dark Falcon
  • 43,592
  • 5
  • 83
  • 98
  • 1
    i tried the double fork and it didnt work for some reason in my situation. double fork was also recommended in another stack question I had but generally felt it was not exactly the most optimal way to do this – Will Bowman Feb 07 '12 at 02:19
  • I would agree, which is why I think the signal handler is better, but I thought I'd mention it. – Dark Falcon Feb 07 '12 at 13:17