Чтобы определить, завершилась ли вызываемая программа аварийно или успешно, можно использовать возвращаемый код завершения процесса. В popen() нельзя напрямую получить код завершения, но можно использовать pclose() для получения кода возврата.
Рассмотрим пример:
Код: Выделить всё
#include <iostream>
#include <cstdio>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
#include <cerrno>
int exec_and_check(const char* cmd, std::string& output) {
std::array<char, 128> buffer;
output.clear();
// Открываем поток
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (!pipe) {
throw std::runtime_error("popen() не удалось открыть поток");
}
// Читаем вывод
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
output += buffer.data();
}
// Получаем код завершения процесса
int return_code = pclose(pipe.get());
if (return_code == -1) {
// Ошибка вызова pclose()
throw std::runtime_error("Ошибка при вызове pclose()");
}
// В Linux/Unix система, если программа завершилась аварийно,
// код завершения обычно отличается от 0.
// В POSIX, код возврата процесса в диапазоне 0-255.
// Если программа завершилась аварийно из-за сигнала, то return_code обычно
// содержит информацию о сигнале (например, сигнал 9 или 11).
// Можно проверить так:
if (WIFSIGNALED(return_code)) {
int sig = WTERMSIG(return_code);
std::cerr << "Программа завершилась аварийно из-за сигнала: " << sig << std::endl;
return sig; // Возвращает номер сигнала
} else if (WIFEXITED(return_code)) {
int exit_status = WEXITSTATUS(return_code);
if (exit_status != 0) {
std::cerr << "Программа завершилась с ошибкой, код: " << exit_status << std::endl;
}
return exit_status;
} else {
// Другие случаи
return -1;
}
}
int main() {
std::string output;
int result = exec_and_check("./myapp", output);
std::cout << "Вывод:\n" << output << std::endl;
if (result == 0) {
std::cout << "Программа завершилась успешно.\n";
} else if (result > 0) {
std::cout << "Программа завершилась с ошибкой, код: " << result << std::endl;
} else {
std::cout << "Программа завершилась аварийно, сигнал: " << result << std::endl;
}
return 0;
}
Обратите внимание:
pclose() возвращает статус, который нужно интерпретировать с помощью WIFEXITED(), WEXITSTATUS(), WIFSIGNALED(), WTERMSIG().
Для этого нужно подключить <sys/wait.h> (в Unix системах).
На Windows подход чуть иной, и для получения кода завершения лучше использовать CreateProcess() и WaitForSingleObject(), а также GetExitCodeProcess().