[SOLVED] TThread - Property problem (SIGSEGV ?)

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
mark332
Beiträge: 202
Registriert: Do 16. Mai 2013, 13:49
OS, Lazarus, FPC: Windows 10 H.P. (x64) / Ubuntu 14.04.X
CPU-Target: AMD Octacore 4.0GHz

[SOLVED] TThread - Property problem (SIGSEGV ?)

Beitrag von mark332 »

Hey Leute,

nach etwas Zeit, melde ich mich (leider) mal wieder,
ich schreibe derzeit eine Anwendung, die einen Thread benötigt, um längere JSON-Aktionen auszuführen,
da dieser Thread zwischendurch ein paar Dateien benötigt und ich ohnehin schon eine Thread-Klasse zum Download von Dateien habe, habe ich diese natürlich
auch im Thread1 genutzt.

Wir haben im Prinzip also:
Hauptthread --(startet)--> Subthread [Subthread1] --(startet)--> Subthread [Subthread2]

Soweit klappt das alles auch ganz gut.
Allerdings soll der Subthread-1 eine Variable schreiben, in der die derzeitige Aktion (als String) steht.
Klappt auch... erstmal.
Denn, wenn der Thread1 seine Variable aus dem eigenen Aktionsstring und dem des Subthreads 2 zusammenstellt, wird eine SIGSEGV-Exception im Hauptthread geworfen.

Codebeispiel:

Code: Alles auswählen

 
procedure TMyThread.Execute;
 
...
 
DThread := TDownLoadThread.Create(True); //Start pausiert, damit wir noch werte setzen können.
DThread.URL := URL;
DThread.Destination := Path;
DThread.Start;
 
while (DThread.HasTerminated=False) and (not Terminated) do begin
tempStr := DThread.Downloadstatus; //Downloadstatus auslesen
 
//[DownloadStatus ist eine Property mit ": String read pDownloadStatus;" (dieser wird vom Thread gesetzt)]
 
pStatus := ('Retreving Index : '+tempStr+'%'); //Aktuellen Threadstatus zusammensetzen | Debugger markiert diese Zeile
end;
 
...
 
end;
 


Im Anwendungsthread steht nichts anderes, als:

Code: Alles auswählen

 
procedure Tfm_Launcher.Button1Click(Sender: TObject);
var
  StartThread : TMyThread;
begin
  StartThread:=TMyThread.Create(True);
  StartThread.Start;
 
  while StartThread.HasTerminated=False do begin
      Label_status.caption:= StartThread.Status; //Status ist eine Property mit ": String read pStatus;"
      Update;
  end;
end;
 


Ich weiß, dass man theoretisch den Download auch ohne Extra-Thread machen könnte, allerdings bin ich neugierig, was hier der Fehler ist,
damit ich ihn nicht später nochmal mache :mrgreen:

Ich hoffe, ihr versteht, was ich versuche zu tun :oops:

MfG

mark332
Zuletzt geändert von mark332 am Mo 22. Dez 2014, 11:21, insgesamt 2-mal geändert.
------------------------------------------------------------
Warum gibt es hier eigentlich kein [SPOILER][/SPOILER] ?

magnetron
Beiträge: 44
Registriert: Di 4. Nov 2014, 14:04

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von magnetron »

Hallo mark332,

fehlt da nicht etwas wie InterlockedExchange oder eine critical section ?
Der mainthread (Button1Click) greift ja auf TMyThread.Status zu und führt
irgendeinen getter pStatus aus (im main thread kontext).
pStatus wird ja aber auch gleichzeitig von Execute beschrieben ?

Grüße, Stefan

mark332
Beiträge: 202
Registriert: Do 16. Mai 2013, 13:49
OS, Lazarus, FPC: Windows 10 H.P. (x64) / Ubuntu 14.04.X
CPU-Target: AMD Octacore 4.0GHz

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von mark332 »

Ich weiß leider nicht, ob ich dir ganz folgen,kann :3

Bedeutet das, dass ich dafür sorgen muss, dass die variable nicht gleichzeitig geschrieben und,gelesen wird ?

Magst du das einmal veranschaulichen ?

Mfg

Mark332
------------------------------------------------------------
Warum gibt es hier eigentlich kein [SPOILER][/SPOILER] ?

magnetron
Beiträge: 44
Registriert: Di 4. Nov 2014, 14:04

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von magnetron »

ja, das würde ich so sehen, ohne Profi zu sein.
TMyThread macht (in seiner execute Mehtode) irgendwas mit pStatus.
Der MainThread liest diese Variable im main thread Kontext über
Button1Click aus.
Bitte im Tutorial nachlesen über Threads, da steht viel drin.
wenn zwei Thread (evtl. gleichzeitig) auf ein und dieselbe Variable zugreifen
crasht das Programm - irgendwann irgendwie...wenn es eben mal zufällig gleichzeitig passiert.

Mit InterlockedExchange kannst Du zwei Pointer Threadsafe austauschen,
ansonsten siehe TCriticalsection, damit können dann auch ganze Methoden synchronisiert werden.
Oder, alternativ übergibt Dein TMyThread die neu errechnete Variable an den main Thread
mittels Synchronize.
Alle drei Varianten sollten das Problem lösen.
Grüße, Stefan

Nachtrag:
ich sehe irgendwie nicht durch wo der "subthread" ist.
Wenn eine SIGSEGV immer an einer bestimmten Stelle auftritt, dann ist eventuell
noch irgendwo ein weiterer bug drin. Der sollte aber dann mit dem entwanzer zu finden sein.

mark332
Beiträge: 202
Registriert: Do 16. Mai 2013, 13:49
OS, Lazarus, FPC: Windows 10 H.P. (x64) / Ubuntu 14.04.X
CPU-Target: AMD Octacore 4.0GHz

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von mark332 »

okay danke, werd ich mir anschauen :)

Was die Exception betrifft, werde ich vom Debugger übrigens immer in die Zeile geschixkt, wo pStatus geschrieben wird, falls das hilft .

Mfg

Mark332
------------------------------------------------------------
Warum gibt es hier eigentlich kein [SPOILER][/SPOILER] ?

magnetron
Beiträge: 44
Registriert: Di 4. Nov 2014, 14:04

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von magnetron »

hmm, naja also mir hilft das jetzt nicht.pStatus ist wohl ein String der irgendwo definiert ist ?
Also muss der ja exisitieren.
Allerdings, wenn das prog crasht weil noch nicht Threadsafe, dann sicher dort.

Mir fiel noch auf, dass zwischen DThread.Downloadstatus und TMyThread.Execute
natürlich das gleiche Problem besteht wie zum Hauptthread.
Wenn es akzeptabel ist, dass ab und an ein paartausend Taktzyklen gewartet wird, dann
sieh Dir TCriticalsection für die Synchronisation zwischen den beiden Threads an.
Und Synchronize für die Übergabe von TMyThead zum MainThread oder
an dieser Stelle Interlockedexchange.
Anzumerken ist, dass der Main Thread nicht in eine Criticalsection laufen darf,
sonst crasht es auch. Ich glaube dieser Fakt ist so deutlich nicht im Tutorial erkennbar.

Das heisst zum Mainthread hin entweder Synchronize und gleich eine ganze Methode
im Mainthread ausführen.
Oder Mainthread mittels Queueasynccall benachrichtigen und dieser holt dann von TMyThread das Ergebnis ab
(dann aber ohne Criticalsection sondern z.B. mit Interlockedexchange).
Grüsse Stefan

mark332
Beiträge: 202
Registriert: Do 16. Mai 2013, 13:49
OS, Lazarus, FPC: Windows 10 H.P. (x64) / Ubuntu 14.04.X
CPU-Target: AMD Octacore 4.0GHz

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von mark332 »

Werde ich mir auch mal anschauen, melde mich dann :)

Schonmal danke, für die Hilfe

MfG

mark332
------------------------------------------------------------
Warum gibt es hier eigentlich kein [SPOILER][/SPOILER] ?

Bitschubser
Beiträge: 61
Registriert: Mo 27. Aug 2012, 15:43

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von Bitschubser »

Solange die gemeinsam genutzten Variablen statisch und maximal 32bit groß sind sollte das alles ohne spezielle Synchronisationsmechanismen funktionieren.
Sobald man eine statische Struktur hat, die größer als 32bit ist muss man damit leben können, dass sich die einzelnen Elemente unabhängig voneinander zwischen 2 Lesezugriffen ändern (weil dann Schreib- und Lesezugriff verschachtelt sein können) - hat man mit der unabhängigen Änderung ein Problem muss man Synchronisationsmechanismen verwenden.
Bei dynamischen Variablen (z.B. auch diverse neumodische Stringtypen) muss man immer Synchronisationsmechanismen verwenden - stell dir vor die Schreibroutine braucht mehr Platz, fordert den an, kopiert den alten String und/oder schreibt was neues in den neuen Speicherplatz - und gibt den alten Speicherplatz frei während die Leseroutine gerade den String am alten Speicherplatz abarbeitet...
Critical section sollte sich immer mit wenig Aufwand nutzen lassen, Synchronize etc. braucht Units die man z.B. bei einer Konsolenanwendung nicht per Default drin hat - und vielleicht in einer Konsolenanwendung auch nicht haben will...

Ach so: Ich hab hier ein System (mit völlig veralteter Lazarus/fpc-Version, was ich zur Zeit nicht updaten kann/will) da wirft der Debugger mir gelegentlicht in Thread A einen SIGSEGV oder auch eine E/InOut an völlig unverdächtiger Stelle in Thread B, wenn ich in Thread A mit Run oder StepOver weiterlaufen lasse - in Ruhe gelassen ist das Programm schon einige Wochen durchgelaufen - könnte also sein, dass man hier erst Fehler erzeugt wenn man versucht reinzugucken.
Mir fällt gerade auf - wieder ein Punkt wo Lazarus Delphi kaum nachsteht :roll:

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von mse »

Bitschubser hat geschrieben:Solange die gemeinsam genutzten Variablen statisch und maximal 32bit groß sind sollte das alles ohne spezielle Synchronisationsmechanismen funktionieren.

Darauf kann man sich bei Mehrkern-Prozessoren nicht mehr verlassen, (Stichwort cache-RAM). Es müssen die verschiedenen interlocked*() Funktionen für ununterbrechbaren Zugriff auf Ordinalwerte verwendet werden.

Bitschubser
Beiträge: 61
Registriert: Mo 27. Aug 2012, 15:43

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von Bitschubser »

mse hat geschrieben:
Bitschubser hat geschrieben:Solange die gemeinsam genutzten Variablen statisch und maximal 32bit groß sind sollte das alles ohne spezielle Synchronisationsmechanismen funktionieren.

Darauf kann man sich bei Mehrkern-Prozessoren nicht mehr verlassen, (Stichwort cache-RAM). Es müssen die verschiedenen interlocked*() Funktionen für ununterbrechbaren Zugriff auf Ordinalwerte verwendet werden.


Ich hab vergessen zu schreiben, dass ich hiermit einfache Kommunikation in eine Richtung meinte - Einer schreibt und Einer oder Mehrere lesen.
Für Read-Modify-Write-Zugriffe (und das decken ja die Interlocked-Funktionen ab) gilt meine Aussage natürlich nicht.
Oder gibt es tatsächlich Mehrkernprozessoren die im Cache oder wo auch immer in <32Bit Einheiten adressieren und so einen Zugriff auf eine longint "auseinanderreißen" könnten?
Die Interlocked-Funktionen kannte ich übrigens noch gar nicht.
Sollten die nicht in http://wiki.freepascal.org/Multithreaded_Application_Tutorial/de erwähnt werden?

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von mse »

Es ist einfach so, dass der der schreibt sich nicht darauf verlassen kann, dass die die lesen das lesen was er gerade geschrieben hat. ;-)
Das Stichwort dazu ist "memory barrier". Die interlocked*() Funktionen beinhalten auch eine memory barrier AFAIK.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von mschnell »

Bitschubser hat geschrieben:Sollten die nicht in http://wiki.freepascal.org/Multithreaded_Application_Tutorial/de erwähnt werden?


Multithreadding wird vom fpc/Lazarus Team nur mit niedriger Priorität behandelt (aber nicht nur dort !)

Für den "Einsteiger" ist es zu komplex (vor allem seit Multi-Prozessor der Standard ist): er sollte es nicht machen, und andere müssen sich eben durchbeißen/durchfragen.

-Michael

mark332
Beiträge: 202
Registriert: Do 16. Mai 2013, 13:49
OS, Lazarus, FPC: Windows 10 H.P. (x64) / Ubuntu 14.04.X
CPU-Target: AMD Octacore 4.0GHz

Re: TThread - Property problem (SIGSEGV ?)

Beitrag von mark332 »

Ich habe mein Problem jetzt mithilfe von "Synchronize" und einem "Sleep(40)" in der Schleife "gelöst",

für mich hat sich das damit jetzt erledigt ;P

Danke für eure Antworten :mrgreen:

MfG

mark332
------------------------------------------------------------
Warum gibt es hier eigentlich kein [SPOILER][/SPOILER] ?

Antworten