Jump to content

[Java] Raspberrypi & Java


Masder

Recommended Posts

Im Grunde schon *gruebel*

 

Also, nur um mein momentanes Verständnis mal zu validieren, die IPconnection und addDevice Methodik läuft wie folgt:

 

[*]Initialisieren der IPConnection, damit werden die Streams zum brickd geöffnet, die CallbackLoop und der Receiver-Thread gestartet.

[*]Device (z.B. TemperatureIR) wird instanziert und damit eine Sende- und eine Empfangs-Semaphore erstellt (die Queue lass ich mal fallen). Die Empfangs-Semaphore wird gleich mal mit einem aquire "belastet" und die UID decoded. Der Konstruktor registriert dann noch seine spezifischen Callback-Listener und fertig.

[*]Per addDevice wird im Grunde nun eine Art "ping - bist Du da?"-Message an den brickd geschickt.

[*]Dann wird mit einem tryAcquire auf eine Antwort gewartet.

[*]Sendet der brickd die Antwort, dann wird sie vom Receiver-Thread aufgegriffen. Der gibt die Nachricht wieder in die IPConnection (handleMessage) und wenn dort erkannt wird, dass es die Antwort zu einer "ping - bist Du da?"-Message ist, dann wird der addDevice-Vorgang durch den Aufruf von handleAddDevice abgeschlossen.

[*]In handleAddDevice wird geschaut ob die Message zum letzten hinzugefügten addDevice-Aufruf passt. Wenn ja, dann wird das Device "registriert" und die Semaphore released.

[*] Der wartende Haupt-Thread kann jetzt weiter machen.

 

Ich hoffe ich habe nicht zu viele Dinge unter den Tisch fallen lassen, aber im Groben müsste das passen.

 

Das einzige wo ich ins Grübeln gekommen bin ist beim Punkt 6. Wenn ich eine "ping - bist Du da?"-Antwort-Message bekomme die nicht zu meine Gerät passt, dann wird diese einfach verworfen und weiter darauf gewartet, dass eine passende Message kommt. Würde nun noch ein addDevice gemacht, dann wird das vorher in der Variable addDevice gehaltene Device überschrieben und auf dessen Registrierung gewartet.

 

Klingt grundsätzlich alles nicht wirklich falsch. Und wie da ein sleep(1) Wunder wirkt, keine Ahnung. Und jetzt ärgere ich mich, dass meine RPi beim Freund an der Solaranlage hängt und nicht vor mir liegt.  :(

 

Schönen Abend noch,

#arald

Link to comment
Share on other sites

Das ist alles soweit richtig. Es haben sich aber in der letzten Version der Java Bindings einige Detail beim Locking geändert.

 

- Die semaphoreAnswer wurde entfernt und deren Funktion über die responseQueue realisiert.

 

- addDevice ist jetzt thread-safe. Vorher konnten mehrere Threads gleichzeitig addDevice auf eine IPConnection aufrufen und sich gegenseitig die pendingAddDevice Variable überschreiben. Das ist jetzt verbessert.

 

Das hat aber alles hier für diese Problem keine Auswirkung.

 

Wenn das sleep(1) dazuführt, dass Linux einen anderen Prozess scheduled, dann vielleicht ja auch brickd. Und wenn das nicht passiert dann passiert ... keine Ahnung :)

 

Daher meine Frage ins Blaue, ob das Problem auch auftritt, wenn das Java Programm auf dem R-Pi ist und der brickd auf einem anderen Rechner. Wenn es dann ohne sleep(1) geht heißt dass ... bin ich mir gerade nicht sicher was das dann sagen will.

 

Wie du siehst mehr Fragen als Antworten :)

Link to comment
Share on other sites

Sagen wir es so, Sleeps yields usw wild einfügen und entfernen sind typische Methoden um Threading-Fehler im eigenen Code zu entlarven. Vielleicht ist der neue Code noch fehlerhaft?

 

Ich habe noch nicht reingeschaut, deswegen ist das eine böse Unterstellung von mir. Aber beispielsweise sind nahezu alle heutigen Desktop PCs Multi-Core, der RPi bestimmt nicht. Insofern würde es mcih nciht wundern, wenn der Threading-Fehler findet die vorher keiner gesehen hat.

 

Ich tauche nachher mal in den Code, falls jemand schneller ist kann er ja mal folgendes Testen:

Im Windows-Task-Manager (Linux kann sowas bestimmt auch) die CPU-Affinität des Java-Prozesses auf nur eine CPU einschränken, damit wird das Programm Single-Core ausgeführt.

Dazu sollte das Programm auf eine Nutzereingabe oder so warten bevor es mit addDevice beginnt um genug zeit zu verschaffen die Affinität zu verändern.

 

edit: Ich sehe auf den ersten Blick auch keine Fehler im Locking (angenommen die SychronousQueue wird von jeder Standardbibliothek korrekt implementiert)

 

Okay, eine Sache ist mir aufgefallen, diese kann zu dem Verhalten führen, dass bei zwei hintereinander kommenden AddDevice das zweite fehlschlägt.

 

handleAddDevice endet so:

			try {
			pendingAddDevice.responseQueue.put(packet);
		} catch(InterruptedException e) {
			e.printStackTrace();
		}
		pendingAddDevice = null;

 

und der gelockte block von adddevice beginnt so:

synchronized(addDeviceMutex) {
		pendingAddDevice = device;

 

Ich führe den Code jetzt mal böse aus:

AddDevice #1 wartet auf response

HandleAddDevice #1 wird abgearbeitet und nach dem putten in die resp-queue dessen Thread unterbrochen

AddDevice #1 wird fertig (resp-queue gefüllt)

AddDevice #2 beginnt, setzt pendingDevice und wartet auf Antwort

HandleAddDevice #1 beendet sich, setzt pendingDevice auf null

HandleAddDevice #2 wird ausgeführt, aber das pendingDevice ist null, also wird nix getan.

 

Ich denke eine sinnvolle Lösung wäre es, das pendingAddDevice im sync-block der Methode AddDevice zu nullen.

Link to comment
Share on other sites

Ich bin zwar nicht der Threadersteller, aber da ich das gleiche Problem hatte, werde ich das auf jeden Fall Testen. Farnell hat den bisherigen Rekord, meine 10 bestellten RPis sind bereits da - Dienstag bestellt, gestern angekommen.

 

Damit ich wieder testfähig bin, werde mir heute noch 'ne SD-Card holen und erstmal die "alte" Version installieren. Damit sollte das Problem ja reproduzierbar sein. Dann die neue Version und dann werde ich mich wieder melden.

 

Have fun,

#arald

Link to comment
Share on other sites

Gute Nachrichten.

 

(1) Ich habe mit einer RPi und dem alten JAR den alten Stand reproduzieren können. Mehrfache Versuche, mit und ohne Systemlast, immer das identische Ergebnis -> Exceptions durch addDevice.

 

(2) Sleep eingefügt, gleiche Tests wie unter (1), funktioniert.

 

(3) Sleeps entfernt, neue JAR Datei genommen (hier aus dem Thread), gleiche Tests wie in (1) und (2), alles Gut!

 

Frohes Schwitzen noch ...

 

have fun

#arald

Link to comment
Share on other sites

Frage an photron (wahlweise TF): Mindestens in den C#-Bindings besteht der gleiche Fehler... unabhängig davon ob es in diesem Foren-Thread die Ursache ist, sollte er denke ich überall gefixed werden.

 

Richtig, das Problem bestand in allen Bindings und ich habe gerade den Fix committed. Neue Binding Releases gibt es morgen, denke ich.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...