MessageDlg in Thread

Rund um die LCL und andere Komponenten
Antworten
Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

MessageDlg in Thread

Beitrag von Nimral »

Nur zur Sicherheit, ich habe gerade begonnen, mit Synapse zu experimentieren.

Unter den Demos gibt es eine (Delphi) Demo zu https (Datei: httpsserv\http.pas). Hieraus folgendes Codeschnipsel, mein Problem steckt im try Block zur SSL Fehlerbehandlung:

Code: Alles auswählen

procedure TTCPHttpThrd.Execute;
var
  timeout: integer;
  s: string;
  method, uri, protocol: string;
  size: integer;
  x, n: integer;
  resultcode: integer;
begin
  timeout := 1000;

  // Note: There's no need for installing a client certificate in the
  //       webbrowser. The server asks the webbrowser to send a certificate but
  //       if nothing is installed the software will work because the server
  //       doesn't check to see if a client certificate was supplied. If you
  //       want you can install:
  //
  //       file: c_cacert.p12
  //       password: c_cakey
  //
  Sock.SSL.CertCAFile := ExtractFilePath(ParamStr(0)) + 's_cabundle.pem';
  Sock.SSL.CertificateFile := ExtractFilePath(ParamStr(0)) + 's_cacert.pem';
  Sock.SSL.PrivateKeyFile := ExtractFilePath(ParamStr(0)) + 's_cakey.pem';
  Sock.SSL.KeyPassword := 's_cakey';
  Sock.SSL.verifyCert := True;

  try
    if (not Sock.SSLAcceptConnection) or
       (Sock.SSL.LastError <> 0) then
    begin
      MessageDlg('Error while accepting SSL connection: ' + Sock.SSL.LastErrorDesc, mtError, [mbAbort], 0);
      Exit;
    end;
  except
    MessageDlg('Exception while accepting SSL connection', mtError, [mbAbort], 0);
    Exit;
  end;

  
  //read request line
  s := sock.RecvString(timeout);
  if sock.lasterror <> 0 then
    Exit;
  if s = '' then
    Exit;
  method := fetch(s, ' ');
  if (s = '') or (method = '') then
    Exit;
  uri := fetch(s, ' ');
  if uri = '' then
    Exit;
  protocol := fetch(s, ' ');
  headers.Clear;
  size := -1;
  //read request headers
  if protocol <> '' then
  begin
    if pos('HTTP/', protocol) <> 1 then
      Exit;
    repeat
      s := sock.RecvString(Timeout);
      if sock.lasterror <> 0 then
        Exit;
      if s <> '' then
        Headers.add(s);
      if Pos('CONTENT-LENGTH:', Uppercase(s)) = 1 then
        Size := StrToIntDef(SeparateRight(s, ' '), -1);
    until s = '';
  end;
  //recv document...
  InputData.Clear;
  if size >= 0 then
  begin
    InputData.SetSize(Size);
    x := Sock.RecvBufferEx(InputData.Memory, Size, Timeout);
    InputData.SetSize(x);
    if sock.lasterror <> 0 then
      Exit;
  end;
  OutputData.Clear;
  ResultCode := ProcessHttpRequest(method, uri);
  sock.SendString('HTTP/1.0 ' + IntTostr(ResultCode) + CRLF);
  if protocol <> '' then
  begin
    headers.Add('Content-length: ' + IntTostr(OutputData.Size));
    headers.Add('Connection: close');
    headers.Add('Date: ' + Rfc822DateTime(now));
    headers.Add('Server: Synapse HTTP server demo');
    headers.Add('');
    for n := 0 to headers.count - 1 do
      sock.sendstring(headers[n] + CRLF);
  end;
  if sock.lasterror <> 0 then
    Exit;
  Sock.SendBuffer(OutputData.Memory, OutputData.Size);
end;                           
Der Code läuft bei mir erst mal nicht sauber, Ursache scheint mir die Verwendung von MessageDlg in einem Thread.

2021-12-16 07_51_09-Lazarus IDE v2.2.0RC2 - httpserv (debugging ...).png
2021-12-16 07_51_09-Lazarus IDE v2.2.0RC2 - httpserv (debugging ...).png (6.11 KiB) 1506 mal betrachtet

daraufhin folgt dann auch noch ein SIGSEV.

2021-12-16 08_06_11-Error.png
2021-12-16 08_06_11-Error.png (5.59 KiB) 1495 mal betrachtet

Erst mal dachte ich, das liegt daran dass das Delphi Code ist, aber dann fand ich das da:

https://stackoverflow.com/questions/267 ... messagedlg

Die Messages in den Hauptthread zu schaffen oder MessageBox zu verwenden ist nicht das Problem, sondern die Frage, ob ich mich irre? Ist das Synapse Sample tatsächlich weder unter Delphi noch unter FPC lauffähig?

Armin.

Benutzeravatar
theo
Beiträge: 10498
Registriert: Mo 11. Sep 2006, 19:01

Re: MessageDlg in Thread

Beitrag von theo »

Ich würde es auf jeden Fall grundsätzlich nicht so machen.
Ein Server poppt nicht blockierende Nachrichtenfenster auf, sondern loggt seine Fehler in eine Datei/System, oder gibt sie dem Client zurück, falls dies schon möglich ist.
Zum Testen könnte er auch mit writeln auf die Konsole schreiben.

Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

Re: MessageDlg in Thread

Beitrag von Nimral »

Na ja, es ist eine Demo, da könnte man Fehlermeldungen am Server vielleicht tolerieren. Aber er poppt ja garnichts auf, sondern schmiert ab.

Writeln wäre m.E. auch problematisch, geht bei einem GUI Projekt unter Windows nicht ohne Weiteres.

Ich würde die Messages für ein Demo-Projekt vermutlich per Synchronize in ein TMemo auf dem Hauptformular schaffen wollen.

Aber sind wir einer Meinung: das Demo-Projekt läuft so wie es ist unter Windows schlecht bis garnicht, weder unter Delphi noch unter FPC?

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6212
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: MessageDlg in Thread

Beitrag von af0815 »

Nimm statt Writeln einfach Debuln aus den Paket LazLogger. Das kann man je nach Bedarf auf die Konsole (wenn vorhanden), Datei oder sonstwo hinleiten. https://wiki.freepascal.org/LazLogger
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

Re: MessageDlg in Thread

Beitrag von Nimral »

Im Moment schwebt mir ein "nettes" Programm vor, das sich auch gut zur Fehlersuche durch Nichtprogrammierer und Konsolenmuffel eignet, das also schön brav in der GUI mitloggt was es tut, und das Fehler farbig hervorhebt (Synchronize in ein TRichEdit). Einfach nur so zum Spaß, zum Lernen, und weil ich es mir so einbilde :-)

Lazlogger ist sicher gut gemeint, aber wir gehen OT.

Topic war: ist MessageDlg außerhalb des Haupt-Threads tatsächlich sowohl unter Delphi als auch unter FPC ein no-go, der Demo-Code mithin fehlerhaft?

Armin.
Zuletzt geändert von Nimral am Do 16. Dez 2021, 09:49, insgesamt 1-mal geändert.

PascalDragon
Beiträge: 832
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: MessageDlg in Thread

Beitrag von PascalDragon »

Nimral hat geschrieben:
Do 16. Dez 2021, 07:57
Die Messages in den Hauptthread zu schaffen oder MessageBox zu verwenden ist nicht das Problem, sondern die Frage, ob ich mich irre? Ist das Synapse Sample tatsächlich weder unter Delphi noch unter FPC lauffähig?
Da die Delphi VCL recht direkt auf der Windows API aufsetzt, kann es sein, dass es funktioniert einen Nachrichtendialog in einem Thread anzuzeigen, aber das ist nicht garantiert. Die LCL ist da etwas mehr abstrahiert, das heißt da ist das eher nicht der Fall und hängt auch vom Widgetset ab (Qt zum Beispiel prüft das sogar aktiv ab). Arbeite im Allgemeinem nach dem Prinzip, dass alle Interaktion mit der GUI aus dem Hauptthread heraus stattfinden muss. Dazu bietet sich dann TThread.Synchronize oder TThread.Queue an.
FPC Compiler Entwickler

Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

Re: MessageDlg in Thread

Beitrag von Nimral »

Die oben abgelichtete Exception von CheckSynchronize mit nachfolgendem Absturz mit SIGSEV in customform.inc weist irgendwie drauf hin, dass MessageDlg aus einem Thread auch unter Windows nicht funktioniert.

Benutzeravatar
theo
Beiträge: 10498
Registriert: Mo 11. Sep 2006, 19:01

Re: MessageDlg in Thread

Beitrag von theo »

Mich würde eher interessieren, warum der MessageDlg angezeigt werden soll.
Da muss der Server ja erst einen Fehler ausspucken, damit das überhaupt geschieht.
Wäre dieser Fehler nicht interessanter zu untersuchen?
Wie gesagt, hat mMn ein MessageDlg in einem Server/Daemon sowieso nichts zu suchen.

Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

Re: MessageDlg in Thread

Beitrag von Nimral »

Den Fehler hatte ich natürlich untersucht, die SSL Dlls wurden im Programmverzeichnis erwartet aber nicht gefunden, aber das ist eine andere unglückliche Geschichte (beide gehören seit annähernd 10 Jahren zum Windows Standardlieferumfang, werden aber nicht im Windows Verzeichnis gesucht und auch nicht gefunden wenn man OpenSSL separat auf der Maschine installiert und PATH dort hin zeigen lässt). Und es gibt sicher noch 100 weitere Fehlerquellen aus dem Themebereich "Zertifikate" abzuhandeln

Ich finds so wie der Code gebaut wurde auch unglücklich. Und bis zu einem gewissen Grad auch inkonsequent, denn anderswo, z.B. beim kritischen "execute" - "bind" - "listen", gibt es überhaupt keinen Fehlercheck. Wenn der Port bereits belegt ist (was sowohl bei 80 als auch bei 443 ziemlich sicher der Fall ist) macht der Code einfach ungerührt weiter und fängt sich in einer Endlosschleife, weil der Port nie gebunden wurde und der Task dadurch nie Daten bekommt.

--> als Demo/Tutorial finde ich solche Beispiele nur unwesentlich besser als gar keine, daher bin ich als Nebenmission auf dem Trip, bessere Beispiele zu machen. Sie zielen auf Einsteiger im Jahr 2021, das sind m.W. Leute, die um Konsolen einen weiten Bogen machen, die nicht bereits Tools in der Tasche haben um Logfiles on the fly anzuzeigen, die man übrigens auch erst bekäme wenn man den Sample-Code selber auf den LazLogger umstricken würde, und die erwarten, dass die ersten Gehversuche, die eh schon schwer genug sind, out-of-the-box reibungslos funktionieren, ohne dass man noch Schlachten an Nebenfronten schlagen muss bevor man seinen ersten Client angebunden bekommt.

Andererseits tue ich mir schwer, Programmierprofis, die mir Lichtjahre voraus sind, schludriger Arbeit zu bezichtigen, und Alternativen zur Diskussion zu stellen, so lange ich mir nicht ganz sicher bin. MessageDlg in einem Thread einzusetzen, obwohl das sowohl unter Delphi als auch unter FPC gar nicht gehen kann, wäre so ein Fall. Dass das Programm abstürzt würde eigentlich sofort auffallen, wenn man den Code ein einziges Mal laufen lässt. Dazu reicht es, die beiden SSL DLLs, die ja m.W. seit geschätzt einem Jahrzehnt zum Standardlieferumfang von Windows gehören - nicht sinnloser Weise ins Programmverzeichnis zu kopieren. Zumindest könnte man eine sprechende Fehlermeldung erwarten.

Dass ein "richtiger" Daemon gar keine GUI haben sollte sehe ich (zu Lernzwecken) dagegen nicht so eng. Man führt das Programm während der Entwicklung ja lange Zeit als User aus, möglicherwseise sogar unter dem Debugger, meistens wird es überhaupt nie als richtiger Daemon ausgeführt werden oder wenn dann erst nach der "Lernphase".

Ich finds auch nicht gut, dass das Sample - das ja zu den ganz grundlegenden gehört - erst mal nur für Delphi vorliegt, wobei das aber in der Lazarus Seite zu Synapse nicht erwähnt wird. Wenn man dort seine Reise in die Web--Programmierung beginnt, kommt man nicht weit, bevor man sich eine blutige Nase nach der Anderen holt.

PascalDragon
Beiträge: 832
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: MessageDlg in Thread

Beitrag von PascalDragon »

Nimral hat geschrieben:
Do 16. Dez 2021, 11:05
Den Fehler hatte ich natürlich untersucht, die SSL Dlls wurden im Programmverzeichnis erwartet aber nicht gefunden, aber das ist eine andere unglückliche Geschichte (beide gehören seit annähernd 10 Jahren zum Windows Standardlieferumfang, werden aber nicht im Windows Verzeichnis gesucht und auch nicht gefunden wenn man OpenSSL separat auf der Maschine installiert und PATH dort hin zeigen lässt). Und es gibt sicher noch 100 weitere Fehlerquellen aus dem Themebereich "Zertifikate" abzuhandeln
Ich weiß ja nicht was du für ein Windows hast, aber bei meinem Windows 10 auf der Arbeit findet sich nur die libcrypto.dll von LibreSSL und die ist für SSL Kommunikation nicht genug, da hierfür die libssl.dll zusätzlich benötigt wird. Und erstere existiert auch nicht seit „annähernd 10 Jahren”, sondern erst seit irgendeiner Version von Windows 10 und Windows 10 ist gerade mal 6 Jahre alt.

Ich sollte echt mal schauen, dass ich eine SChannelSockets Unit schreibe, die direkt auf SChannel, Microsofts SSL Implementierung aufsetzt, dann braucht man gar keine zusätzlichen Bibliotheken unter Windows mehr, wenn man z.B. fpHTTPServer einsetzt.
FPC Compiler Entwickler

Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

Re: MessageDlg in Thread

Beitrag von Nimral »

PascalDragon hat geschrieben:
Do 16. Dez 2021, 14:14
Ich weiß ja nicht was du für ein Windows hast, aber bei meinem Windows 10 auf der Arbeit findet sich nur die libcrypto.dll von LibreSSL und die ist für SSL Kommunikation nicht genug,
Nun, ich hab zwei Rechner durchsucht nach c:\windows\???eay*.dll, der eine hat WIndows 7(!), der andere ein ziemlich aktuelles Windows 10. Bei beiden finden sich beide Dateien in c:\windows\syswow64. Ich kann Dir aber natürlich nicht sagen, ob sie immer schon da waren, oder ob ein Microsoft Update oder gar irgendeine später installierte Software sie dort abgekippt hat. Eigentlich ist es egal. Es scheint, dass viele Windows Systeme die Libraries schon haben. Meine hatten sie ja auch, aber sie wurden trotzdem nicht geladen. Wenn die Dateien in einem Systemverzeichnis vorhanden sind, sollten sie m.E. von LoadLibrary auch automatisch gefunden werden. In allen anderen Fällen wäre eine sprechende Fehlermeldung angebracht. Die hätte der Demo-Code auch produziert, aber da er MessageDlg zur Anzeige aus einem 2. Thread heraus bemüht hat hat der Versuch, den Fehler anzuzeigfen, stattd essen das Programm abgeschossen.

Ich sehe also zwei einfache Verbesserungsmöglichkeiten: die Libraries aktiv suchen (ich glaube man kann den Pfad vor der Initialisierung von SSL setzen), bzw. herausfinden warum die Suche bei meinen beiden Windows Rechnern versagt hat, und die Fehlermessages per Synchronize in den GUI Thread schieben.

Wenn Du die Unit schreiben möchtest, wäre jetzt ein passender Zeitpunkt: ich habe ein kleineres Projekt laufen bis 3/2021 wo ich intensiv mit Sockets gegen alle möglichen Hosts programmieren muss, und gleichzeitig einen Client für Android und iOS zur Verfügung stellen, der ebenfalls SSL benützt. Das wäre der ideale Zeitpunkt, so eine Bibliothek intensiv zu testen, ich würde nach Kräften mithelfen.

Und mit den gewonnenen Erkenntnissen und Codeschnippseln das Wiki ausbauen.

HG, Armin

PascalDragon
Beiträge: 832
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: MessageDlg in Thread

Beitrag von PascalDragon »

Nimral hat geschrieben:
Do 16. Dez 2021, 14:50
Nun, ich hab zwei Rechner durchsucht nach c:\windows\???eay*.dll, der eine hat WIndows 7(!), der andere ein ziemlich aktuelles Windows 10. Bei beiden finden sich beide Dateien in c:\windows\syswow64. Ich kann Dir aber natürlich nicht sagen, ob sie immer schon da waren, oder ob ein Microsoft Update oder gar irgendeine später installierte Software sie dort abgekippt hat.
Wenn sie nur in SysWoW64 sind, dann ist es sehr wahrscheinlich, dass die von einer Drittsoftware installiert wurden, da Microsoft sowohl 32- als auch 64-bit Bibliotheken liefern würde.
Nimral hat geschrieben:
Do 16. Dez 2021, 14:50
Eigentlich ist es egal. Es scheint, dass viele Windows Systeme die Libraries schon haben.
Haben sie eben nicht. Nur weil das vielleicht bei deinen beiden Systemen der Fall ist, kannst du deswegen nicht auf die Allgemeinheit schließen.
Nimral hat geschrieben:
Do 16. Dez 2021, 14:50
Meine hatten sie ja auch, aber sie wurden trotzdem nicht geladen. Wenn die Dateien in einem Systemverzeichnis vorhanden sind, sollten sie m.E. von LoadLibrary auch automatisch gefunden werden.
Hast du denn mit einer 32- oder einer 64-bit Anwendung getestet? Die Bibliotheken liegen bei dir in SysWoW64, das heißt es sind 32-bit Bibliotheken und die werden natürlich nur von einer 32-bit Anwendung gefunden.
Nimral hat geschrieben:
Do 16. Dez 2021, 14:50
In allen anderen Fällen wäre eine sprechende Fehlermeldung angebracht. Die hätte der Demo-Code auch produziert, aber da er MessageDlg zur Anzeige aus einem 2. Thread heraus bemüht hat hat der Versuch, den Fehler anzuzeigfen, stattd essen das Programm abgeschossen.
Du solltest am besten beim Start der Anwendung InitSSLInterface aus der Unit OpenSSL aufrufen und dann überprüfen, ob diese True oder False zurückgibt.
Nimral hat geschrieben:
Do 16. Dez 2021, 14:50
Wenn Du die Unit schreiben möchtest, wäre jetzt ein passender Zeitpunkt: ich habe ein kleineres Projekt laufen bis 3/2021 wo ich intensiv mit Sockets gegen alle möglichen Hosts programmieren muss, und gleichzeitig einen Client für Android und iOS zur Verfügung stellen, der ebenfalls SSL benützt. Das wäre der ideale Zeitpunkt, so eine Bibliothek intensiv zu testen, ich würde nach Kräften mithelfen.
Vielleicht ergibt sich zwischen den Jahren mal Gelegenheit...
FPC Compiler Entwickler

Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

Re: MessageDlg in Thread

Beitrag von Nimral »

Der Vollständigkeit halber: ich habe auf allen Systemen die 32 Bit Version von Lazarus (i386-win32-win32/win64) laufen, und produziere damit ausschließlich 32 Bit Apps. Die Libraries hätten also m.E. gefunden werden sollen.

Antworten