#c #signals #fork #exec #zombie-process
#c #сигналы #fork #exec #зомби-процесс
Вопрос:
У меня есть сама программа-демон fork
, которая затем выполняет бесконечный цикл проверки системных условий, и когда выполняются определенные условия, она запускает команду. Эти команды могут выполняться долго, что означает, что они должны быть асинхронными, поэтому я использую 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)
это должно игнорировать дочерний элемент и позволить процессам инициализации пожинать их. Почему эти зомби все еще задерживаются?
Ответ №1:
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);
}