Kann ich stdout / stderr getrennt erfassen und die ursprüngliche Reihenfolge beibehalten?

8

Ich habe eine Windows-Anwendung mit der nativen Win32-API geschrieben. Meine App startet andere Prozesse und erfasst die Ausgabe und hebt die stderr-Ausgabe rot hervor.

Um dies zu erreichen, erstelle ich eine separate Pipe für stdout und stderr und verwende sie in der STARTUPINFO-Struktur, wenn CreateProcess aufgerufen wird. Ich starte dann einen separaten Thread für jedes stdout / stderr-Handle, das aus der Pipe liest und die Ausgabe in ein Fenster protokolliert.

Dies funktioniert in den meisten Fällen gut. Das Problem, das ich habe, ist, dass, wenn der Kind-Prozess in stderr und stdout in schneller Folge protokolliert, meine App manchmal die Ausgabe in der falschen Reihenfolge anzeigt. Ich gehe davon aus, dass dies zwei Threads zum Lesen von jedem Handle verwendet.

Ist es möglich, stdout und stderr in der ursprünglichen Reihenfolge zu schreiben, in die sie geschrieben wurden, und dabei zwischen den beiden unterscheiden zu können?

    
flashk 09.10.2009, 19:20
quelle

6 Antworten

3

Ich bin mir ziemlich sicher, dass es nicht möglich ist, das geschriebene Programm so zu schreiben, dass es in Pakete schreibt und jedem einen Zeitstempel hinzufügt. Ohne das können Sie normalerweise planen, dass das Puffern in der Standardbibliothek des Child-Prozesses stattfindet. Wenn sie also über die Pipe an den Parent übertragen werden, besteht eine gute Chance, dass sie bereits außer Betrieb sind.

    
Jerry Coffin 10.10.2009, 21:01
quelle
2

In den meisten Implementierungen von stdout und stderr, die ich gesehen habe, ist stdout gepuffert und stderr nicht. Im Grunde bedeutet das, dass Sie nicht garantieren können, dass sie in Ordnung sind, selbst wenn Sie das Programm auf einer geraden Kommandozeile ausführen.

Ссылка

Die kurze Antwort: Sie können nicht sicherstellen, dass Sie die Zeilen in der Reihenfolge lesen, in der sie in cmd.exe angezeigt werden, da die Reihenfolge, in der sie auf cmd.exe angezeigt werden, nicht garantiert ist.

    
Evan Larkin 12.10.2009 15:41
quelle
0

Nicht wirklich, das würde man meinen, aber std_out steht unter der Kontrolle der Systementwickler - genau wie und wann std_out geschrieben wird, unterliegt dem System-Scheduler, der bei meinen Tests Problemen untergeordnet ist, die nicht so dokumentiert sind.

Ich habe eines Tages etwas geschrieben und an einem der Geräte im System gearbeitet, während ich den Code im Editor geöffnet hatte und festgestellt habe, dass das System dem Treiber in Echtzeit Priorität einräumt. c-Code etwa ein Zehntel so wichtig wie der proprietäre Code.

Das zu invertieren, damit Sie die Reihenfolge der Schreibvorgänge sequentiell ordnen, ist eine Herausforderung, um es gelinde auszudrücken.

    
Nicholas Jordan 09.10.2009 23:37
quelle
0

Sie können stderr auf stdout umleiten:

command_name 2>&1

Dies ist möglich in C mit Rohren, soweit ich mich erinnere.

UPDATE: Oh, tut mir leid - ich habe den Teil vermisst, dass ich zwischen den beiden unterscheiden konnte. Ich weiß, dass TextMate es irgendwie mit einem Benutzer-sichtbaren Code gemacht hat ... Habe noch nicht eine Weile gesucht, aber ich werde einen Blick darauf werfen. Aber könnten Sie nach einigem Nachdenken etwas wie Open3 in Ruby verwenden? Sie müssten sowohl STDOUT als auch STDERR gleichzeitig sehen, aber niemand sollte eine bestimmte Reihenfolge der Ausgabe in Bezug auf diese beiden erwarten.

UPDATE 2: Beispiel von was ich in Ruby meinte:

%Vor%

... wo print3.rb gerade ist:

%Vor%

Anstatt die Ausgabe direkt auf puts zu werfen, könnten Sie eine Nachricht an einen Beobachter senden, der es in Ihrem Programm ausdrucken würde. Entschuldigung, ich habe kein Windows auf diesem Rechner (oder irgendeinen sofort verfügbaren), aber ich hoffe, dies illustriert das Konzept.

    
Benjamin Oakes 10.10.2009 16:01
quelle
0

Ich bin mir ziemlich sicher, dass selbst wenn Sie sie nicht trennen , Sie immer noch nicht garantieren können, dass sie sich gegenseitig in der richtigen Reihenfolge austauschen.

    
shoosh 11.10.2009 16:41
quelle
0

Da die Absicht darin besteht, die Ausgabe eines vorhandenen Programms zu kommentieren, muss jedes mögliche Verschachteln der zwei Ströme korrekt sein. Der ursprüngliche Entwickler hat entsprechende flush () -Aufrufe platziert, um sicherzustellen, dass eine verbindliche Bestellung eingehalten wird.

Wie zuvor erläutert, notieren Sie jedes Fragment, das mit einem Zeitstempel geschrieben wurde, und verwenden Sie dies, um die tatsächlich von den Ausgabegeräten gesehene Sequenz wiederherzustellen.

    
Pekka 12.10.2009 18:30
quelle

Tags und Links