C ++ popen pipe некорректно закрывается с помощью pclose для & quot; ps aux & quot; команда

Я использую MacOS и хочу выполнить команду «ps aux» и получить ее вывод через мое приложение. Я написал метод, который выполняет команды, используя функцию popen:

std::string exec(const char* cmd) {

char buffer[128];
std::string result = "";

FILE* pipe = popen(cmd, "r");
if (!pipe) throw std::runtime_error("popen() failed!2");
try {
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
} catch (...) {
pclose(pipe);

throw;
}
pclose(pipe);return result;
}

У меня есть цикл, который постоянно выполняет функцию exec («ps aux»). Проблема в том, что канал из popen не закрыт, что я проверил, используя команду «lsof» из терминала. Примерно через 20 секунд приложение открывает около 300 дескрипторов файлов, которые не позволяют приложению открывать больше каналов (выполняя команду «ps aux») из цикла.

Я обнаружил, что функция exec отлично работает для других команд (канал закрывается правильно), например, «netstat», поэтому в команде «ps aux» должно быть что-то, что препятствует закрытию канала.

Я много искал об этой проблеме, но не нашел никакого решения.
Может кто-нибудь, пожалуйста, укажите мне в правильном направлении?

Спасибо!

2

Решение

Я не вижу, что конкретно не так с вашим кодом. Для этих вещей я использую пользовательское средство удаления с std::unique_ptr чтобы убедиться, что файл закрывается на всех возможных выходах.

Также обратите внимание, что не рекомендуется использовать цикл while(eof(...)) по нескольким причинам. Один из них не установлен в случае ошибки. Больше информации здесь.

// RAII piped FILE*

// custom deleter for unique_ptr
struct piped_file_closer
{
void operator()(std::FILE* fp) const { pclose(fp); }
};

// custom unique_ptr for piped FILE*
using unique_PIPE_handle = std::unique_ptr<std::FILE, piped_file_closer>;

//
unique_PIPE_handle open_piped_command(std::string const& cmd, char const* mode)
{
auto p = popen(cmd.c_str(), mode);

if(!p)
throw std::runtime_error(std::strerror(errno));

return unique_PIPE_handle{p};
}

// exception safe piped reading
std::string piped_read(std::string const& cmd)
{
std::string output;

if(auto pipe = open_piped_command(cmd, "r"))
{
char buf[512];
while(auto len = std::fread(buf, sizeof(char), sizeof(buf), pipe.get()))
output.append(buf, len);

if(std::ferror(pipe.get()))
throw std::runtime_error("error reading from pipe");
}

return output;
}

призвание auto output = piped_read("ps aux"); сотни раз в моей системе не выдает ошибку с этим кодом.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]