Einzelnen Beitrag anzeigen

MStoll

Registriert seit: 15. Nov 2005
131 Beiträge
 
Turbo Delphi für Win32
 
#1

TIdHTTPServer: Programmabsturz bei langwieriger ResponseInfo-Berechnung

  Alt 30. Dez 2013, 23:21
Hallo,

ich schreibe gerade eine Anwendung zur Steuerung einer Startampel für Motorsport-Veranstaltungen mittels eines Raspberry Pi und compiliere diese mit FreePascal 2.6.0. Dieser steuert über die GPIO-Ports die eigentliche Ampel-Schaltung bzw. liest deren Zustand aus. Dazu enthält die Anwendung auch einen Webserver auf Indy-Basis (TIdHTTPServer). Gleichzeitig ist an das Kamera-Interface des Pi auch noch eine passende Kamera angeschlossen, die einen Videostream liefert, aus dem dann interrupt-gesteuert bei Auslösen einer Lichtschranke das aktuelle Frame des Videostreams zwischengespeichert wird. Dies zur Überwachung des Startbereiches, für den die Startampel zuständig ist.

Eben dieses zwischengespeicherte Videoframe möchte ich als JPEG-Bild über den HTTP-Server ausgeben. Geht auch alles wunderbar, solange nur 1 Client auf das Webinterface zugreift. Sobald mehrere auf das Videobild zugreifen, stürzt die Software ab. Ich muss folgendes dazu sagen: die Umwandlung des Videoframes in das JPEG-Format einschließlich der Ausgabe in einen MemoryStream dauert ca. 2-3 Sekunden. Solange müssen alle Webclients warten, da die Erstellung mittels einer Critical Section geschützt ist.

Nochmal eine kurze Funktionsübersicht:
- Steuerung bzw. Auslesen der Startampel mittels GPIOs und Interrupts
- Abfangen einzelner Video-Frames der CSI-Kamera über einen GPIO-Interrupt, der durch eine angeschlossene Lichtschranke ausgelöst wird
- Ausgabe des Startampel-Zustands (Zählerstand, welche roten bzw. grünen LEDs leuchten etc.) + Steuerung über Webinterface mittels von TIdHTTPServer abgeleiteter Klasse

Nach langem Testen habe ich herausgefunden, dass die zeitliche Dauer der JPEG-Erstellung das Problem ist, da ich den Absturz der Anwendung auch dadurch herbeiführen kann, dass ich in das DoCommandGet-Event ein Sleep(2000) einfügen kann. Dies führt dann selbst beim Aufruf einfacher Text-Pages zum Absturz, unabhängig davon, ob ich "ContentText" oder "ContentStream" für die Ausgabe verwende. Dann auch schon, wenn nur 1 Webclient auf das Webinterface zugreift.

Wenn ich in der "TIdHTTPResponseInfo.WriteContent"-Methode (TIdCustomHTTPServer.pas)die "FConnection.IOHandler.Write"-Aufrufe auskommentiere, geht naturgemäß zwar keine Webausgabe, aber dann stürzt auch mein Programm nicht ab. Bei kurzen Antwortzeiten (kleine Seiten, Bilder etc.), die nur wenige Millisekunden benötigen, funktioniert alles wunderbar.

Ein kurzes Code-Beispiel:
Delphi-Quellcode:
procedure THTTPServer.DoCommandGet(AContext: TIdContext;
      ARequestInfo: TIdHTTPRequestInfo;
      AResponseInfo: TIdHTTPResponseInfo);
var
  fs : TFileStream;
  fileExt, document, content, filePath, fileName : string;
  commandNumber : Integer;
begin
  document := 'HTTP' + StringReplace(ARequestInfo.Document, '..', '', [rfReplaceAll]);
  if document = 'HTTP/then
    document := document + 'index.html';

  filePath := SysUtils.ExtractFilePath(document);
  fileName := SysUtils.ExtractFileName(document);
  try
   // ...
   // Hier werden ContentText bzw. ContentStream befüllt
   // ...
  finally
    if Assigned(AResponseInfo.ContentStream) then
    begin
      try
        Sleep(2000); // <--- führt zum kommentarlosen Crash
        AResponseInfo.WriteContent;
      except on e: exception do
        Writeln(e.Message);
      end;
    end
    else if AResponseInfo.ContentText <> 'then
    begin
      Sleep(2000); // <--- führt ebenfalls zum kommentarlosen Crash
      AResponseInfo.WriteContent;
    end;
  end;
end;
Es wird auch keine Fehlermeldung angezeigt. Die Anwendung ist eine Konsolenanwendung (ohne LCL) und ist dann einfach weg.

Ich hoffe, dass von euch jemand Erfahrungen und evtl. auch Lösungsansätze in der Richtung hat. Vielen Dank für eure Mühen!
"Man soll nie mehr essen als mit Gewalt reingeht!" (n.n.)

Geändert von MStoll (30. Dez 2013 um 23:23 Uhr) Grund: Compiler-Angabe vergessen
  Mit Zitat antworten Zitat