у меня проблемы с моим проектом, я создаю дочерние процессы с помощью fork, затем завершаю их с помощью kill(pid,SIGINT), а затем перезапускаю их после второго прерывания процесса Linux вылетит на экран входа в систему. так что также возможно, что на самом деле происходит сбой в gnome или моем оконном менеджере я не знаю, как это исправить. вот код, который приводит к сбою
#include <iostream>
#include <signal.h>
#include <thread>
const int CHILDREN = 3;
bool is_active;
using namespace std;
void signalHandler(int signum)
{
cout << "Interrupt signal (" << signum << ") received.\n";
// cleanup and close up stuff here
// terminate program
is_active = false;
}
pid_t fork_process(int process_nr)
{
pid_t c_pid;
c_pid = fork();
if (c_pid == -1)
{
perror("failure to fork new process");
return -1;
}
else if (c_pid == 0)
{ // child process
signal(SIGINT, signalHandler);
is_active = true;
while (is_active)
{
}
cout << "child " << process_nr << " EXIT" << endl;
return -1;
}
return c_pid;
}
pid_t restart_process(int process_nr, pid_t pid)
{
cout << "restart process " << process_nr << endl;
pid_t new_c_pid;
kill(pid, SIGINT);//THIS IS WHERE THE CRASH HAPPENS
sleep(3);
new_c_pid = fork_process(process_nr);
return new_c_pid;
}
int main(int argc, char const *argv[])
{
int ret;
pid_t c_pid[CHILDREN];
for (int i = 0; i < CHILDREN; i++)
{
ret = fork_process(i);
if (ret == -1)
return 0;
c_pid[i] = ret;
cout << "parent created child " << i << " with c_pid " << c_pid[i] << endl;
}
int to_restart = 1;
this_thread::sleep_for(chrono::seconds(16));
// restart the selected process
c_pid[to_restart] = restart_process(to_restart, c_pid[to_restart]);
this_thread::sleep_for(chrono::seconds(16));
// restart the selected process
c_pid[to_restart] = restart_process(to_restart, c_pid[to_restart]);//THIS IS WHERE THE CRASH HAPPENS
this_thread::sleep_for(chrono::seconds(16));
return 0;
}
с Makefile
CC = g++
CFLAGS = -Wall -g
output: main.o
$(CC) $(CFLAGS) -o output main.o
main.o: main.cpp
$(CC) $(CFLAGS) -c main.cpp
clean:
rm *.o output
Спасибо за помощь.
однократный перезапуск работает нормально, поэтому я не знаю, как двойной вызов приведет к сбою я запустил его с помощью GDB и отметил, где происходит сбой. однако это произойдет не сразу, а через 5 секунд после выполнения функции kill().
Почему to_restart
всегда 1
? Это выглядит неправильно.
Добавьте очистку std::cout
(используйте std::endl
вместо новой строки) и добавьте больше вывода. Это должно помочь вам сузить круг вопросов. Перенаправьте вывод в файл (или перенаправьте его на команду tee, чтобы сохранить вывод в файл и отобразить его в терминале). Пример добавленного вывода: родительский pid в дочерних процессах, pid
для отправки SIGINT
(и текущий pid процесса). И многое другое (например, все аргументы всех функций и все возвращаемые значения всех функций).
@JesperJuhl, так как я хочу дважды перезапустить процесс 1
Если у вас есть экран входа в систему, Linux не аварийно завершился. Ваши процессы вышли из строя, потому что вы их убили. Чего именно вы ожидали?
Когда вы restart_process
, вы не проверяете значение результата для -1
. Итак, когда раздвоенный дочерний процесс возвращается, он продолжается, как и в основном процессе, за исключением того, что в следующий раз, когда он убивает предполагаемого дочернего процесса, он вызывает kill(-1, ...)
, который убивает все, на что у вас есть разрешение.
Во всяком случае, что-то в этом роде.
спасибо за помощь, я действительно должен был это увидеть..... почему это может привести к сбою Linux на рабочем столе? наверное, увидел бы это, если бы у меня были результаты.....
@robybert Я давно не использовал настольную Unix, но обычно это работает так: экран входа в систему запускается от имени пользователя root, поэтому он может получить доступ к вашему паролю и фактически выполнить вход для вашего пользователя. Когда это происходит, среда рабочего стола запускается от имени вашего пользователя и, конечно же, все, что вы запускаете самостоятельно. kill(-1)
убивает все, что вам разрешено удалять, то есть каждую программу, которую запустил ваш пользователь, включая среду рабочего стола, которую вы используете. Когда он исчезнет, менеджер входа заметит это и снова покажет вам экран входа в систему.
ОТ: Родительский процесс должен извлечь выгоду из дочерних процессов при их выходе. Вызвав одну из функций семейства
wait
.