Как выйти из процесса, если ребенок терпит неудачу?

Программа, с которой я работаю, требует для запуска вторичного исполняемого файла (для сжатия ресурсов). По причинам обработки ошибок мне нужно возвращаемое значение дочернего процесса. Согласно справочной странице system,

Если все системные вызовы завершаются успешно, возвращаемым значением является статус завершения дочерней оболочки, используемой для выполнения команды. (Состояние завершения оболочки — это состояние завершения последней выполненной ею команды.)

В соответствии с этим, состояние возврата моего вызова system должно быть возвращаемым значением вызванного процесса. Но, похоже, это не так. Вместо этого, когда Генератор возвращает EXIT_FAILURE, программа получает EXIT_SUCCESS или 0. Я что-то неправильно понимаю?

Мой код ниже.

// Checks to see if the generator still exists using access().
bool asset_generator_availability = CheckAssetGenerator();

if (!asset_generator_availability) LogMessage("Assets already generated.");
else
{
    LogWarning(
        "Assets still uncompressed and unformatted. Running the Generator.");

    u8 generator_state = system("./AssetGenerator && rm AssetGenerator");
    // Here is the problem line.
    if (generator_state == EXIT_FAILURE) exit(EXIT_FAILURE);
}

Вы слишком рано перестали читать справочную страницу: в последних двух случаях возвращаемое значение представляет собой «статус ожидания», который можно проверить с помощью макросов, описанных в waitpid(2). (т. е. WIFEXITED(), WEXITSTATUS() и т. д.).

tofro 05.07.2024 08:29

@tofro Ах, ладно. Но как можно использовать эти функции?

Zenais 05.07.2024 08:30

«Код выхода» ошибочно относится как к значению, возвращаемому main, так и к целому числу, возвращаемому wait, которое содержит это значение, но сдвинуто. В данном случае речь идет о последнем. Используйте макросы из wait's docs.

ikegami 05.07.2024 08:40

@ikegami Справочная страница waitpid пролила очень мало света на то, что делает любая из этих функций. Есть ли дополнительная ссылка, которую я должен увидеть?

Zenais 05.07.2024 08:42

Обновлено ссылкой, которая четко документирует макросы (а не функции).

ikegami 05.07.2024 08:43
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Эта проблема возникает потому, что когда система успешно запускает вызванный процесс, она не возвращает прямое возвращаемое значение запущенного процесса. Вместо этого он возвращает «статус ожидания», который можно проверить с помощью макроса, описанного в waitpid(2). (т. е. WIFEXITED(), WEXITSTATUS() и т. д.). На страницах руководства есть более подробная информация по этому вопросу, но для вашего кода вы можете использовать WIFEXITED и WEXITSTATUS следующим образом:

if (WIFEXITED(generator_state) && WEXITSTATUS(generator_state) == EXIT_FAILURE)
{
exit(EXIT_FAILURE);
}

В этом коде WIFEXITED проверяет, что дочерний процесс завершился нормально, а WEXITSTATUS проверяет статус выхода дочернего процесса. Однако system также предоставляет другие возвращаемые значения, если команда имеет значение NULL, дочерний процесс не может быть создан или его статус не может быть получен, оболочка не может быть выполнена в дочернем процессе. Чтобы учесть это, вы можете использовать несколько других макросов waitpid следующим образом:

if (generator_state == -1)
{
    exit(EXIT FAILURE);
} //exits if system fails to create the child process or retrieve it's status.
else
{
    if (WIFEXITED(generator_state))
    {
        int exit_status = WEXITSTATUS(generator_state);
        if (exit_status == EXIT_FAILURE)
        {
            exit(EXIT_FAILURE);
        } //exits on the failure in the child code. You could add other failures in the same way.
        else
        {
        //Handle successful completion of the asset generator.
        }
    }
    else if (WIFSIGNALED(generator_state))
    {
        int signum = WTERMSIG(generator_state);
        LogError("Asset Generator was terminated by signal: %d", signum);
        exit(EXIT_FAILURE);
    }// Logs if the generator is terminated by a signal, and the signal number.
    else
    {
        if (WEXITSTATUS(generator_state) == 127)
        {
            LogError("Failed to execute shell in child process.");
        } //Logs if the shell couldn't be executed in the child process.
        else
        {
            LogError("Asset Generator terminated abnormally.");
            exit(EXIT_FAILURE);
        }// Logs if the generator is terminated in some other unexpected way.
    }
}

Ради примера я использовал функцию LogError для отдельных ошибок, так как видел, что в предыдущем коде у вас было LogWarning. Если у вас нет функции LogError, вы можете создать ее или использовать какой-либо другой метод для учета отдельных ошибок. .

Надеюсь это поможет!

Обновлено: Ниже приведены страницы руководства для system и wait. https://man7.org/linux/man-pages/man3/system.3.htmlhttps://man7.org/linux/man-pages/man2/waitpid.2.html

Это решение, похоже, ничего не изменило. Стоит ли мне также изменить оформление моего звонка system?

Zenais 05.07.2024 08:48

Неважно, проблема возникла из-за приведения типа u8 из результата system вызова i32. Это сработало безупречно. Спасибо!

Zenais 05.07.2024 08:49

@Zenais system возвращает int, а не u8 или i32

ikegami 05.07.2024 08:53

@ikegami i32 (32-битное целое число со знаком) — это то, что system возвращает, насколько мне известно. Нет?

Zenais 05.07.2024 08:54

@Zenais, Нет. Опять же, он возвращает int, а не i32.

ikegami 05.07.2024 08:55

@ikegami Согласно gnu.org/software/gnu-c-manual/…, «int — 32-битный тип данных int может содержать целочисленные значения в диапазоне от -2 147 483 648 до 2 147 483 647. Вы также можете обратиться к этот тип данных как подписанный int или подписанный». i32 — это просто мои внутренние определения типов для int32_t.

Zenais 05.07.2024 08:57

@Zenais, int не гарантированно будет 32-битным. Это гарантированно будет только 16 бит. И он может быть на любой размер больше. Использование int32_t неправильно. system возвращает int. /// Также сомнительна практика запутывания использования стандартных и известных int32_t.

ikegami 05.07.2024 08:58

@Anon520 Anon520, вряд ли твое решение будет правильным. Другие коды ошибок, кроме 1, он не считает ошибками, хотя так и должно быть. Он не считает убийство ребенка по сигналу ошибкой, хотя так и должно быть. (Да, ОП тоже допустил эти ошибки, но это вас не оправдывает.)

ikegami 05.07.2024 09:00

@ikegami справедливая точка зрения. Я обновил ответ, чтобы иметь возможность обрабатывать многие другие возвращаемые значения, предоставляемые системой, а также любые другие неожиданные ошибки.

Anon520 05.07.2024 09:53

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