Могу ли я захватить stdout / stderr отдельно и поддерживать первоначальный порядок? - PullRequest
8 голосов
/ 09 октября 2009

Я написал приложение для Windows, используя собственный API Win32. Мое приложение запустит другие процессы, сохранит вывод и выделит вывод stderr красным цветом.

Для этого я создаю отдельный канал для stdout и stderr и использую их в структуре STARTUPINFO при вызове CreateProcess. Затем я запускаю отдельный поток для каждого дескриптора stdout / stderr, который читает из канала и записывает вывод в окно.

В большинстве случаев работает нормально. Проблема, с которой я сталкиваюсь, заключается в том, что если дочерний процесс регистрирует в stderr и stdout в быстрой последовательности, мое приложение иногда отображает вывод в неправильном порядке. Я предполагаю, что это связано с использованием двух потоков для чтения из каждого дескриптора.

Возможно ли захватить stdout и stderr в том порядке, в котором они были записаны, при этом они могут различать два?

Ответы [ 6 ]

3 голосов
/ 11 октября 2009

Я почти уверен, что это невозможно, если не считать порожденную программу для записи в пакеты и добавления метки времени к каждому. Без этого вы обычно можете планировать буферизацию в стандартной библиотеке дочернего процесса, поэтому к тому времени, когда они даже передаются через канал к родительскому процессу, есть хороший шанс, что они уже вышли из строя. 1001 *

2 голосов
/ 12 октября 2009

В большинстве реализаций stdout и stderr, которые я видел, stdout буферизуется, а stderr - нет. По сути, это означает, что вам не гарантируется, что они будут в порядке даже при запуске программы в командной строке.

http://en.wikipedia.org/wiki/Stderr#Standard_error_.28stderr.29

Краткий ответ: Вы не можете гарантировать, что вы читаете строки в том же порядке, в котором они появляются в cmd.exe, потому что порядок, в котором они появляются в cmd.exe, не гарантируется.

0 голосов
/ 12 октября 2009

Поскольку целью является аннотирование выходных данных существующей программы, любое возможное чередование двух потоков должно быть правильным. Первоначальный разработчик разместил соответствующие вызовы flush (), чтобы обеспечить выполнение любого обязательного заказа.

Как объяснено ранее, запишите каждый фрагмент, записанный с отметкой времени, и используйте ее для восстановления последовательности, фактически видимой устройствами вывода.

0 голосов
/ 11 октября 2009

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

0 голосов
/ 10 октября 2009

Вы можете перенаправить stderr на стандартный вывод:

command_name 2>&1

Насколько я помню, это возможно в Си с использованием труб.

ОБНОВЛЕНИЕ: О, извините - пропустил часть о способности различать два. Я знаю, что TextMate сделал это каким-то образом, используя своего рода код, видимый пользователю ... Давненько не искал, но я посмотрю. Но, подумав, не могли бы вы использовать что-то вроде Open3 в Ruby? Вам нужно будет одновременно смотреть и STDOUT, и STDERR, но на самом деле никто не должен ожидать определенного порядка вывода этих двух.

ОБНОВЛЕНИЕ 2: Пример того, что я имел в виду в Ruby:

require 'open3'

Open3.popen3('ruby print3.rb') do |stdin, stdout, stderr|
  loop do
    puts stdout.gets
    puts stderr.gets
  end
end

... где print3.rb просто:

loop do
  $stdout.puts 'hello from stdout'
  $stderr.puts 'hello from stderr'
end

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

0 голосов
/ 10 октября 2009

Не совсем, вы бы так подумали, но std_out находится под контролем проектировщиков системы - как именно и когда пишется std_out, зависит от системного планировщика, который по моим тестам подчиняется проблемам, которые не так задокументированы.

Однажды я написал кое-что и выполнил работу на одном из устройств в системе, когда у меня был открыт код в редакторе, и обнаружил, что система отдает приоритет драйверу в реальном времени, оставив мой осторожный… созданный c-код где-то примерно на одну десятую важнее проприетарного кода.

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

...