C++ kill() приводит к сбою Linux на экране входа в систему

у меня проблемы с моим проектом, я создаю дочерние процессы с помощью 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().

ОТ: Родительский процесс должен извлечь выгоду из дочерних процессов при их выходе. Вызвав одну из функций семейства wait.

Some programmer dude 30.04.2024 00:17

Почему to_restart всегда 1? Это выглядит неправильно.

Jesper Juhl 30.04.2024 00:19

Добавьте очистку std::cout (используйте std::endl вместо новой строки) и добавьте больше вывода. Это должно помочь вам сузить круг вопросов. Перенаправьте вывод в файл (или перенаправьте его на команду tee, чтобы сохранить вывод в файл и отобразить его в терминале). Пример добавленного вывода: родительский pid в дочерних процессах, pid для отправки SIGINT (и текущий pid процесса). И многое другое (например, все аргументы всех функций и все возвращаемые значения всех функций).

Some programmer dude 30.04.2024 00:22

@JesperJuhl, так как я хочу дважды перезапустить процесс 1

robybert 30.04.2024 00:26

Если у вас есть экран входа в систему, Linux не аварийно завершился. Ваши процессы вышли из строя, потому что вы их убили. Чего именно вы ожидали?

user207421 30.04.2024 01:30
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда вы restart_process, вы не проверяете значение результата для -1. Итак, когда раздвоенный дочерний процесс возвращается, он продолжается, как и в основном процессе, за исключением того, что в следующий раз, когда он убивает предполагаемого дочернего процесса, он вызывает kill(-1, ...), который убивает все, на что у вас есть разрешение.

Во всяком случае, что-то в этом роде.

спасибо за помощь, я действительно должен был это увидеть..... почему это может привести к сбою Linux на рабочем столе? наверное, увидел бы это, если бы у меня были результаты.....

robybert 30.04.2024 01:19

@robybert Я давно не использовал настольную Unix, но обычно это работает так: экран входа в систему запускается от имени пользователя root, поэтому он может получить доступ к вашему паролю и фактически выполнить вход для вашего пользователя. Когда это происходит, среда рабочего стола запускается от имени вашего пользователя и, конечно же, все, что вы запускаете самостоятельно. kill(-1) убивает все, что вам разрешено удалять, то есть каждую программу, которую запустил ваш пользователь, включая среду рабочего стола, которую вы используете. Когда он исчезнет, ​​менеджер входа заметит это и снова покажет вам экран входа в систему.

Christian Stieber 30.04.2024 01:38

Другие вопросы по теме