Fork / exec оставляя зомби-процессы даже с сигналом - PullRequest
0 голосов
/ 11 апреля 2019

У меня есть сама программа-демон fork s, затем выполняется бесконечный цикл, проверяющий системные условия, и, когда выполняются определенные условия, она запускает команду. Эти команды могут выполняться долго, что означает, что они должны быть асинхронными, поэтому я использую fork и execvp для запуска команд. Мой код выглядит так:

int main(int argc, char *argv[])
{
  signal(SIGCHLD, SIG_IGN);
  pid_t pid, sid;
  pid = fork();
  if (pid < 0)
  {
    exit(EXIT_FAILURE);
  }
  if (pid > 0)
  {
    exit(EXIT_SUCCESS);
  }
  umask(0);
  sid = setsid();
  if (sid < 0)
  {
    exit(EXIT_FAILURE);
  }
  if ((chdir("/")) < 0)
  {
    exit(EXIT_FAILURE);
  }
  while (1)
  {
    // Check conditions
    ...
    if (conditions_met)
    {
      pid_t pid2, sid2;
      pid2 = fork();
      if (pid2 == 0)
      {
        sid2 = setsid();
        // Define command_argv
        ...
        execvp(command_argv[0], command_argv);
      }
    }
  sleep(60);
  }
exit(EXIT_SUCCESS);
}

Это все работает, и мои команды работают нормально - однако, это оставляет процессы зомби. Я впервые пытаюсь использовать fork и exec асинхронно, но я подумал, что signal(SIGCHLD, SIG_IGN) должен игнорировать дочерний элемент и позволить процессам init пожинать их. Почему эти зомби все еще задерживаются?

1 Ответ

2 голосов
/ 11 апреля 2019

Параметр SIG_IGN не сохраняется в fork(), поэтому вам нужно вызвать signal(SIGCHLD, SIG_IGN); в дочернем процессе с циклом, который порождает все команды, а не с исходным родительским процессом.

#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
    pid_t pid, sid;
    pid = fork();
    if (pid < 0)
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    if (pid > 0)
    {
        exit(EXIT_SUCCESS);
    }
    signal(SIGCHLD, SIG_IGN);
    umask(0);
    sid = setsid();
    if (sid < 0)
    {
        perror("setsid");
        exit(EXIT_FAILURE);
    }
    if ((chdir("/")) < 0)
    {
        perror("chdir");
        exit(EXIT_FAILURE);
    }
    while (1)
    {
        // Check conditions
        if (true)
        {
            pid_t pid2, sid2;
            pid2 = fork();
            if (pid2 == 0)
            {
                sid2 = setsid();
                // Define command_argv
                execlp("sleep", "sleep", "1", (char*)0);
            }
        }
        sleep(60);
    }
    exit(EXIT_SUCCESS);
}
...