У меня есть программа на C ++, которая работает над другими. Если он обнаруживает, что процесс больше не работает, он перезапускает его через system
, Проблема в том, что если я убью сторожевой процесс, все запущенные процессы также умрут.
void* ProcessWatchdog::worker(void* arg)
{
//Check if process is running
if( !processRunning )
system("processName /path/to/processConfig.xml &");
}
Новый дочерний процесс запускается правильно и работает без проблем. Но когда родитель (теперь этот ProcessWatchdog
умирает, ребенок тоже умирает. Как я могу порождать дочерний процесс, который полностью независим от родителя?
Я пытался использовать pclose
а также popen
запуск сценариев оболочки, запускающих процессы, и несколько других тактик, но безрезультатно. Я игнорирую SIGHUP
сигналы в дочерних процессах, но они все равно умирают.
В идеале, я бы хотел сказать системе запустить процесс, который полностью независим от родителя. Я хочу ребенка trace
покончить с ребенком, и чтобы он / система не знали, что ProcessWatchdog
начал это в первую очередь.
Есть ли способ, которым я могу сделать это?
Я пишу это на C ++, на Linux.
Попробуйте использовать system
с setsid
перед именем процесса.
system("setsid processname /path/to/processConfig.xml &");
Это запустит программу в новом сеансе.
Этот немного староват, но не получил полного ответа. Вот что я сделал во встроенной системе, чтобы создать дочерний элемент bash, не имеющий отношения к родительскому. Обратите внимание, что я запускаю оболочку bash, а затем запускаю команду в другой оболочке bash. Это не может быть необходимым в вашей ситуации. Для меня это позволило мне сделать некоторое перенаправление ввода / вывода, которое не работало должным образом без него.
Двумя важными понятиями являются setsid () и double fork (). Комбинация этих двух препятствует созданию зомби, когда ребенок-сирота завершает свою работу, а также предотвращает убийство ребенка-сироты, если родитель завершает свою работу.
Существует много других проблем, таких как унаследованные дескрипторы ввода-вывода, рабочий каталог и т. Д., Но этот код выполняет основную работу.
int spawn_orphan(char* cmd) {
char command[1024]; // We could segfault if cmd is longer than 1000 bytes or so
int pid;
int Stat;
pid = fork();
if (pid < 0) { perror("FORK FAILED\n"); return pid; }
if (pid == 0) { // CHILD
setsid(); // Make this process the session leader of a new session
pid = fork();
if (pid < 0) { printf("FORK FAILED\n"); exit(1); }
if (pid == 0) { // GRANDCHILD
sprintf(command,"bash -c '%s'",cmd);
execl("/bin/bash", "bash", "-c", command, NULL); // Only returns on error
perror("execl failed");
exit(1);
}
exit(0); // SUCCESS (This child is reaped below with waitpid())
}
// Reap the child, leaving the grandchild to be inherited by init
waitpid(pid, &Stat, 0);
if ( WIFEXITED(Stat) && (WEXITSTATUS(Stat) == 0) ) {
return 0; // Child forked and exited successfully
}
else {
perror("failed to spawn orphan\n");
return -1;
}
}
Не использовать system(...)
это не многопоточность безопасно.
int pid = fork();
if(pid==0)
{
int rc = execv("processname", "/path/to/processConfig.xml &");
if(rc == -1)
{
printf(stderr, "processname failed to start. %d", errno);
}
...
}
else
{
//continue with the parent
}
Вы должны избегать использования системы.
Не используйте system () из программы с set-user-ID или set-group-ID
привилегии, потому что странные значения для некоторых переменных среды
может быть использован для нарушения целостности системы. Используйте семейство exec (3)
функции вместо
а также, если вы хотите проверить возвращаемое значение или что-нибудь еще
Просто пойти на execl
#include <unistd.h>
#include <stdlib.h>
pid_t pid = fork()
if (pid == -1)
{
exit(EXIT_FAILURE);
}
else if (pid == 0)
{
if (execl("processname", "processname", "/path/to/processConfig.xml", NULL) == -1)
exit(EXIT_FAILURE);
}
else
...
Вы можете быть заинтересованы демон (3) функция библиотеки (внутренне используя два вложенных вилка (2) Системные вызовы). После этого используйте соответствующие execve (2) системный вызов (или связанный Exec (3) функции) …
Вы должны прочитать Расширенное программирование в Linux для большего.
Есть пример execvp в https://github.com/w-A-L-L-e/wash/blob/master/src/wash.cpp. Передача аргументов командной строки иногда является проблемой с функциями exec * от unistd, и передача среды может быть некоторой работой. В любом случае, надеюсь, это поможет …