Ankündigung

Einklappen
Keine Ankündigung bisher.

Verbindungsabbrüche Falcon SDK 6 unter Linux/Docker

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #16
    Hast du das Logging im Falcon aktiviert? Irgendetwas auffälliges in den Logs?

    Kommentar


      #17
      Danke für den Hinweis, bin gerade erst dazu gekommen mir das anzuschauen. Also das Falcon Log läuft ganz normal weiter und ist völlig unauffällig. Ich weiß aber natürlich auch nicht genau, was "auffällig" heißt. Ich sehe keine Fehler und für mich sieht es so aus, als würden auch nachdem meine Anwendung keine Connection mehr hat, weiterhin normal Nachrichten eintreffen. Hier ein Beispiel einer Message, die nach Connection lost meiner App noch kam im Log. Received GroupValue_Write_ind <- 1.1.37 -> 4/1/0 (hc=6) Value=1 .

      Und das geht ewig sauber weiter. Was mir aufgefallen ist: ich kann nichts mehr an den Bus senden und erhalte in der Anwendung keine Events mehr via onGroupMessageReceived. Es fühlt sich so an, als wäre irgendwas gelockt oder so. In meinem Anwendungslogging sehe ich zudem immer wieder als allerletzte Aktion das Abschalten und Auslösen einer Szene.

      Kann ich irgendwie mit der Anwendung einen Deadlock-Zustand oder so erzeugen?
      Die Bus Connection bleibt permanent geöffnet, ich nutze eine Verbindung für die Anwendungs-Lifetime.

      Kommentar


        #18
        Update: Ich kann es innerhalb 1 Minute reproduzieren. Es liegt an den Szenen. Starte ich die Anwendung, und spiele danach ein bisschen mit den Szenen rum (Sende Szene 1, 2, alles aus) dann steht die Connection und nichts geht mehr.

        Bleibt die Frage warum? Und warum ging es problemlos mit einer älteren SDK Version (5.x)?

        Ich werde mir am Wochenende nochmal genau anschauen, was auf dem Bus & in der Anwendung passiert, wenn die Szenen ausgelöst werden.

        Zwei Vermutungen:
        1. die alte App läuft auf dem bisherigen Server parallel, eigentlich mit eigener Adresse, aber vielleicht hab ich irgendetwas übersehen, dass sie sich in die Quere kommen
        2. Ich habe einen Status Speicher für Szenen in der Anwendung implementiert, vielleicht funktioniert hier irgendetwas nicht, was den Thread killt oder lahmlegt und somit die Verbindung blockt.

        Ich tippe eher auf (2). Gerade bin ich erstmal mega happy, dass ich genau weiß, wo ich schauen muss!! Stay tuned

        Kommentar


          #19
          Was der Falcon übelnimmt: im EventHandler längerdauernde Aktionen oder gar blockierende Aufrufe. Am besten einfach nur das Event in eine interne Queue stellen.
          Benutzt du den Thread Pool? Wenn ja, lauern da auch Fallstricke (Stichwort: thread starvation).

          Du kannst mich gerne auch mal direkt kontaktieren, wir sind ja quasi Nachbarn.

          Kommentar


            #20
            Update: Ich bin mir ziemlich sicher die Ursache gefunden zu haben!

            Es scheint grundsätzlich eine Änderung im Falcon SDK (5.x -> 6.x) zu sein, die die Symptomatik auslöst hat. Es geht darum, dass im EventHandler einer zu behandelnden Nachricht vom KNX Bus als Reaktion im gleichen Thread wieder ein Write-Befehl auf den Bus gesendet werden soll. Dadurch entsteht eine Art Deadlock, die Verbindung ist nicht mehr nutzbar und auch ein AutoReconnect greift nicht.

            Für alle die ein ähnliches Problem haben, hier ein paar mehr Details:

            Ich habe eine Klasse BusMonitor, die alle Telegramme auf dem Bus beobachtet. Meine Implementierung nutzt diese Service-Klasse als ein Singleton-Objekt, d.h. es existiert genau 1x im Speicher meiner Applikation. Im Konstruktur dieser Klasse registriere ich einen EventHandler bei einer weiteren Service-Klasse BusConnection, die die gesamte Kommunikation (Lesen, Schreiben, Events registrieren) managed. Dieser EventHandler soll dann alle eingehenden Telegramme verarbeiten. Also ich habe genau eine Instanz, die meine gesamte Bus-Kommunikation managed, und eine weitere Instanz, die sich um die zu verarbeitenden Telegramme vom Bus kümmert, die darauf aufbaut.

            In meinem Fall war es nun so, dass ein spezielles Szenario im Kontext von selbst entwickelten Szenen dazu führte, dass viel weiter unten im Code beim Wechsel des Status einer Szene ein solches Telegram vom Bus empfangen wurde, der Status gespeichert wurde und aufgrund dieses Statuswechsels ein weiterer Schreib-Befehl an den Bus gesendet wurde. Diese ganze Aufruf-Kaskade vom EventHandler bis zum erneuten Schreib-Befehl war innerhalb des gleichen Threads, was scheinbar dazu führte, dass die Connection nicht mehr nutzbar wurde.

            Vereinfacht kann man das Szenario wie folgt darstellen:
            image.png​​
            ​​Man baut eine Bus Connection auf, schreibt irgendwas auf den Bus. Als Folge kommt ein weiteres Telegram (Status changed to "true") unten in den EventHandler rein und der reagiert darauf und sendet erneut einen Write-Befehl, um z. B. das Licht direkt wieder auszuschalten. Passiert letzteres im gleichen Thread, dann steht die Verbindung und nichts geht mehr.

            Die einfachste und schnellste Abhilfe, die ich jetzt getestet habe, ist die gesamte Verarbeitung der Events einfach asynchron zu machen, z. B. durch eine Task:
            image.png

            Macht man es so, gibt es keine Deadlocks oder Abbrüche mehr. Ich hab es zwar nur kurz getestet und noch nicht über einen längeren Zeitraum, aber das vorher reproduzierbare Verhalten, lässt sich nun nicht mehr reproduzieren.

            Klaus Gütter hatte den alternativen Vorschlag alle Events in eine Queue zu packen und die Queue asynchron abzuarbeiten. Das könnte meiner Meinung nach sogar noch eine bessere Lösung sein, da man dadurch erneut parallele Nutzungen einer Verbindung reduziert.

            Habt ihr noch andere Ideen, was man hier verbessern kann? Oder gibt es evtl. sogar BestPractices seitens Falcon?
            Ich bin gespannt auf eure Antworten


            Die Moral von der Geschicht, schreiben tut man im GroupMessageReceived-EventHandler synchron nicht!
            Zuletzt geändert von mymazl; 25.04.2024, 07:42.

            Kommentar


              #21
              Hallo Marcel,

              ich glaube auch, dass das das Problem ist.

              Task.Factory.StartNew und dann darin einen synchronen Aufruf ist allerdings nicht so gut. Du blockierst damit einen Thread im Thread Pool und das führt möglicherweise zu einen Phänomen, das sich "Threadpool starvation" nennt. Siehe auch:
              https://medium.com/@jaiadityarathore...l-bef2f5a37888
              https://medium.com/criteo-engineerin...e-512c8d570527

              Besser wäre es, die asynchrone Methode zu benutzen:
              Code:
              _ = connection.WriteGroupMessageAsync(...)
              Oder die angesprochene Queue.

              Gruß aus Kalchreuth, Klaus

              Kommentar


                #22
                Ich danke dir, Klaus für deine Hilfe und die Hinweise. Als Lösung nutze ich jetzt erstmal den einfachsten Weg via
                Code:
                _ = connection.WriteGroupMessageAsync(...)​
                Auch wenn ich glaube, dass es so wenige Threads sind, dass Task.StartNew in meinem Fall auch nicht zur Starvation geführt hätte. Die Anwendung und das Haus-Setup hier privat sind so klein, aber die Async Lösung gefällt mir auch einfach besser.

                Ich hoffe, dass die Hinweise evtl. auch p3root helfen

                Kommentar

                Lädt...
                X