Seite 1 von 1

Mutex Thread LinkedList Fehler

Verfasst: 16.08.2013 20:27
von CSHW89
Hi Leute,

mich quält nun schon seit einiger Zeit ein mieser Fehler. Da er in einem recht großen Projekt auftritt, und zudem auch noch sehr sporadisch und zufällig, konnte ich die Ursache lange Zeit nicht finden. Nun kann es sein, dass ich ihm nun etwas auf die Schliche gekommen bin. Allerdings ist immer noch sehr viel Zufall im Spiel, alles sehr strange. Hier man ein kleiner Testcode, der den Fehler erzeugt:

Code: Alles auswählen

Global NewList event.i()
Global mutex = CreateMutex()

Procedure TestThread(hallo)
  Repeat
    LockMutex(mutex)
      If NextElement(event())
        DeleteElement(event())
        AddGadgetItem(0, 0, "Event "+Str(ElapsedMilliseconds()))
      EndIf
    UnlockMutex(mutex)
    
    Delay(10)
  ForEver
EndProcedure

Procedure Main()
  OpenWindow(0, 0, 0, 200, 400, "Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  ListViewGadget(0, 0, 0, 200, 400)
  
  CreateThread(@TestThread(), 0)
  
  Repeat
    event = WaitWindowEvent(10)
    
    If (event = #PB_Event_CloseWindow)
      quit = #True
    EndIf
    
    If (Random(5) = 0)  ; <-- hier Wert verkleinern, falls kein Fehler auftritt
      LockMutex(mutex)
        AddElement(event())
        ResetList(event())
      UnlockMutex(mutex)
    EndIf
    
  Until (quit)
EndProcedure

Main()
Es werden ständig neue Events in eine Liste gepackt (ich richtigen Programm sind es Usereingaben), die ein Thread dann ausliest. Irgendwann friert das Fenster ein, und es passiert gar nichts. Der Debugger kann mir auch nicht mehr sagen, wo ich gerade bin. Das passiert aber auch nur manchmal. Also lasst es ein paar mal laufen, vielleicht auch mit einem kleineren Wert bei Random (z.b. 3 oder 4). Allerdings tauchte bei mir der Fehler auch mal auf, als ich dort 20 stehen hatte. Ich kann nicht erkennen, dass ich dort irgendwelche Deadlocks produziere.

Bei Tests im Originalprogramm habe ich noch merkwürdigere Dinge erlebt, in dem der Programmfluss komplett unkontrolliert wurde. So kam es dann dazu, dass "Test1" ausgegeben wurde, "Test2" aber nicht, obwohl dazwischen nur eine einfache Zuweisung stand:

Code: Alles auswählen

Debug "Test1"
c = d
Debug "Test2"
Ich hoffe, ihr könnt den Fehler bestätigen.

PB: 5.11 / 5.20 Beta, 32 Bit, Threadsafe aktiviert

lg Kevin

Re: Mutex Thread LinkedList Fehler

Verfasst: 16.08.2013 23:52
von STARGÅTE
Das Probem sehe ich gerade darin, dass du AddGadgetItem() noch im LOCK des Thread drin hast.
AddGadgetItem erzeugt aber ein Event, welches von WaitWindowEvent() verarbeitet werden muss/will.
Wenn der Main-Code allerdings gerade im LockMutex() feststeckt, kann kein WaitWindowEvent() aufgerufen werden.
Änder ich den Code so um:

Code: Alles auswählen

  	LockMutex(mutex)
  	If NextElement(event())
  		DeleteElement(event())
  		UnlockMutex(mutex)
  		AddGadgetItem(0, 0, "Event "+Str(ElapsedMilliseconds()))
  	Else
  		UnlockMutex(mutex)
  	EndIf
Läuft er.

oder unten:

Code: Alles auswählen

    If (Random(5) = 0)  ; <-- hier Wert verkleinern, falls kein Fehler auftritt
      If TryLockMutex(mutex)
        AddElement(event())
        ResetList(event())
      UnlockMutex(mutex)
      EndIf
    EndIf
Edit.

Re: Mutex Thread LinkedList Fehler

Verfasst: 16.08.2013 23:58
von CSHW89
Hm ja mist. Mit dem ersten Code funktionierts. Das ist aber definitiv nicht der Fehler im Ursprungsprogramm. Da hab ich im Thread gar keine Änderungen von Gadgets/Window. Also heißts weiter probieren den Fehler anders zu reproduzieren >_<

lg Kevin

Re: Mutex Thread LinkedList Fehler

Verfasst: 17.08.2013 11:04
von helpy
Probier es mal mit folgendem Code aus:

Code: Alles auswählen

Global NewList event.i()
Global mutex = CreateMutex()

Procedure TestThread(hallo)
	Protected text.s
	Repeat
		LockMutex(mutex)
		If FirstElement(event())
			text = "Event " +Str(event()) + " - " + Str(ElapsedMilliseconds())
			DeleteElement(event())
			UnlockMutex(mutex)
			AddGadgetItem(0, 0, text)
		Else
			UnlockMutex(mutex)
			Delay(10)
		EndIf
		
	ForEver
EndProcedure

Procedure Main()
	Protected event, quit
	Protected counter
	
	OpenWindow(0, 0, 0, 200, 400, "Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
	ListViewGadget(0, 0, 0, 200, 400)
	
	CreateThread(@TestThread(), 0)
	
	Repeat
		event = WaitWindowEvent(10)
		
		If (event = #PB_Event_CloseWindow)
			quit = #True
		EndIf
		
		If (Random(5) = 0)  ; <-- hier Wert verkleinern, falls kein Fehler auftritt
			counter +1
			LockMutex(mutex)
			LastElement(event())
			AddElement(event())
			event() = counter
			UnlockMutex(mutex)
		EndIf
		
	Until (quit)
EndProcedure

Main()
Wenn "AddGadgetItem(0, 0, text)" innerhalb des Locks ist, dann bleibt das Programm hängen, wenn der Debugger an ist!
Wenn der Debugger aus ist, läuft es durch.

Re: Mutex Thread LinkedList Fehler

Verfasst: 17.08.2013 17:54
von NicTheQuick
Versuch's mal mit Semaphoren. Dafür sind die eigentlich gedacht.

Re: Mutex Thread LinkedList Fehler

Verfasst: 17.08.2013 19:44
von CSHW89
@helpy: Ich hab ein Fehler in einem ganz anderen Programm, den ich lange Zeit nicht reproduzieren konnte. Ich dachte, dieser Code würde es nun tun. Aber Stargate hat mir ein Strich durch die Rechnung gemacht. Deshalb macht es jetzt hier kein Sinn, weiter zu diskutieren, bis ich entweder eine Idee hab, den Fehler zu beheben, oder dann doch wieder produzieren kann.

@NicTheQuick: Nicht, wenn das Event aus mehreren Daten besteht. Im richtigen Programm hat die Liste "event" noch eine Structure.

lg Kevin

Re: Mutex Thread LinkedList Fehler

Verfasst: 18.08.2013 00:00
von NicTheQuick
Das hat nichts mit mehreren Daten zu tun, sondern mit Effizienz. Eine Semaphore wartet solange ohne den Prozessor zu belasten bis ein anderer Thread ihm wieder "sagt", dass er weiter arbeiten soll, weil z.B. ein neues Element in der Event-Queue ist. Du machst aktuell ein Busy-Wait mit deinem 'Delay(10)'. Das heißt im Wortstcase dauert es immer 10 ms bis der Thread schaut, ob was neues in der Queue ist. Mit Semaphoren hast du das Problem nicht. Semaphoren ersetzen aber auch keinen Mutex. Also nicht verwechseln!

Re: Mutex Thread LinkedList Fehler

Verfasst: 18.08.2013 09:04
von CSHW89
Ah ok, ich dachte, du meintest anstatt der Liste. Aber du meinst, anstatt des Delay und der Prüfung von NextElement. Das könnt ich natürlich machen. Danke
lg Kevin