linux — захватывает вывод процесса в многопоточном переполнении стека

Мои требования просты: запустите процесс, дождитесь его завершения, затем запишите и обработайте его вывод.

Долгое время я использовал следующее:

struct line : public std∷string {
friend std∷istream& operator>> (std∷istream &is, line &l) {
return std∷getline(is, l);
}
};

void capture(std::vector<std::string> &output, const char *command)
{
output.clear();
FILE *f = popen(command, "r");
if(f) {
__gnu_cxx::stdio_filebuf<char> fb(f, ios∷in) ;
std::istream fs(&fb);
std::istream_iterator<line> start(fs), end;
output.insert(output.end(), start, end);
pclose(f);
}
}

И это действительно хорошо работает на однопоточных программах.

Однако, если я вызываю эту функцию из потока, иногда popen() звонок зависает и никогда не возвращается.

Итак, в качестве подтверждения концепции я заменил функцию для этого уродливого хака:

void capture(std::vector<std::string> &output, const char *command)
{
output.clear();
std::string c = std::string(command) + " > /tmp/out.txt";
::system(c.c_str());
ifstream fs("/tmp/out.txt", std::ios::in);
output.insert(output.end(), istream_iterator<line>(fs), istream_iterator<line>());
unlink("/tmp/out.txt");
}

Это некрасиво, но работает, но это заставило меня задуматься, что будет правильный способ захвата вывода процесса в многопоточной программе.

Программа работает на linux во встроенном процессоре powerquiccII.

0

Решение

Видеть это: попен — замки или не нить безопасны? и другие ссылки не кажутся убедительными в том, что popen () должен быть потокобезопасным, поэтому, возможно, поскольку вы используете менее популярную платформу, ваша реализация — нет. Есть ли шанс, что вы можете просмотреть исходный код реализации для вашей платформы?

В противном случае рассмотрите возможность создания нового процесса и ожидания его. Или, эй, придерживайтесь глупого взлома system (), но обработайте его код возврата!

2

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

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