[2.1.2] Segfault, wenn das Videoverzeichnis aktualisiert wird, während das Aufnahmenmenü offen ist

  • Moin!


    Es passiert nicht immer, lässt sich aber mit mehreren Versuchen immer mal wieder provozieren.
    Aufnahmenmenü öffnen, Auswahl auf einer Aufnahme platzieren, "svdrpsend updr" ausführen.
    Evtl. muss "LastReplayed" in der setup.conf auch noch den passenden Namen haben, das hab ich noch nicht verifiziert.


    Code
    2603: void cMenuRecordings::Set(bool Refresh)
    2604: {
    2605:   const char *CurrentRecording = *fileName ? *fileName : cReplayControl::LastReplayed();
    2606:   cMenuRecordingItem *LastItem = NULL;
    2607:   cThreadLock RecordingsLock(&Recordings);
    2608:   if (Refresh) {
    2609:      if (cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()))
    2610:         CurrentRecording = ri->Recording()->FileName();
    2611:      }


    UPDR löscht cRecordings und scannt das Videoverzeichnis komplett neu ein.
    Die cMenuRecordingItem merken sich aber einen Zeiger auf ein cRecording-Objekt. Das existiert dann natürlich nicht mehr.
    Außerdem merkt sich cReplayControl auch keine Kopie des Dateinamen, sondern einen Zeiger auf cRecording::fileName. Wenn aber später cReplayControl::LastReplayed aufgerufen wird, kommt ein Zeiger ins Nirvana zurück.
    Ich hatte nämlich nicht nur an dieser Stelle einen Absturz, sondern auch etwas später in Zeile 2641 beim strcmp mit "CurrentRecording", welches dann einen Wert von 0x85 hatte.


    Sollte cMenuRecordingItem sich eine Kopie des cRecording-Objektes erstellen? Es ist ja immerhin ein "flüchtiges" vdr-Objekt, sprich, kann jederzeit zerstört werden, wenn es nicht gelockt ist.
    Oder sollte der Video-Scanner nicht starten, wenn das Aufnahmenmenü offen ist? Das halte ich aber für die falsche Lösung.
    Ein Workaround wäre (da cMenuRecording::Set ja in diesem Moment einen Lock auf cRecordings hält), dass erst geprüft wird, ob ri->Recording() noch Bestandteil von cRecordings ist. Und wenn nicht, wird es einfach nicht verwendet. Hilft aber auch nicht beim cReplayControl.
    Ich hab also noch keine Lösung, wollte das Problem aber schon mal mitteilen.


    Ich weiß nicht, ob vergleichbares für cTimer und cEvent und deren Menüs gilt, momentan arbeite ich nur mit dem Aufnahmenmenü wegen des Patches, um die erste Verzeichnisebene auszublenden. Ich dachte schon, der wäre Schuld, aber ich hab das mit einem vanilla-vdr nachvollziehen können.


    Lars.

  • Alles klar. Ich bin mir auch nicht sicher, ob das nicht in vdr 2.0.4 auch schon auftritt. So viel hat sich an der Stelle ja nicht geändert, auch wenn da ein paar Dinge hinzugekommen sind, die hier aber nicht hineinspielen.


    Lars.

  • Ich sehe gerade, dass cMenuRecording::RefreshRecording da schon was interessantes und evtl. passendes macht:


    Lars.

  • Zitat

    Alles klar. Ich bin mir auch nicht sicher, ob das nicht in vdr 2.0.4 auch schon auftritt.


    Doch,ist bei mir auch schon passiert.

  • Moin!


    Ich hab mal einen Patch erstellt. Basis ist das Verhalten in cMenuRecording.
    Ich habe eine neue Klasse "cRecordingItem" eingeführt, die das cRecording-Objekt kapselt und bei Bedarf überprüft, ob es noch vorhanden ist. Danach muss nur noch an ein paar Stellen auf "!= NULL" geprüft werden.


    Ist nur ein Ansatz, eine Idee. Die neue Klasse könnten dann auch Plugins usw. nutzen, um sich cRecording-Objekte zu merken.
    cMenuRecording könnte sie natürlich genauso verwenden.


    Bisher konnte ich keinen weitern Absturz provozieren. In cReplayControl hab ich das aber noch nicht drin.


    Lars.

  • Mit cReplayControl hab ich mich wahrscheinlich vertan, fileName ist vom Typ cString, das kopiert den Dateinamen, genauso wie auch fileName in cMenuRecordings.
    Also hat das vermutlich doch was mit dem cRecording-Objekt zu tun gehabt haben.


    Anbei ein etwas erweiterter Patch, bei dem auch cMenuRecording auf cRecordingItem umgestellt ist.


    Lars.

  • Moin!


    Ich hab an ein paar Stellen noch einen Lock auf Recordings eingebaut, wo ich es für sinnvoll erachte. Genau kann ich es nicht abschätzen, ob alle notwendig sind, oder nicht. Aber gestört haben sie in meinen Tests auch nicht.


    Frohe Weihnachten!


    Lars.

  • Ich weiß nicht, irgendwie gefällt mir das nicht.
    Ich würde es lieber so machen wie bei den EPG-Events, die werden auch "ausgefast".
    Kannst du bitte mal stattdessen beiliegenden Patch ausprobieren?
    Damit werden "verschwundene" Recordings aus der Recordings-Liste in die neue VanishedRecordings-Liste verlagert, die dann später, wenn gerade nichts mehr los ist, gelöscht wird.
    Alle eventuell vorhandenen Pointer auf solche Recordings sind damit noch so lange gültig, bis alle Menüs geschlossen und alle sonstigen Aktivitäten beendet sind.
    Außerdem wird bei einem Update nicht erst die ganze Recordings-Liste gelöscht und komplett neu aufgebaut.


    Da diese Änderung nur private Interfaces betrifft müsste ich die sogar in der nächsten 2.0-er Version (2.0.5) einbauen können ohne die APIVERSION erhöhen zu müssen.


    Klaus

  • Scheint nach einem ersten Test mit ~20 Aktualisierungen bei offenem Aufnahmemenü zu funktionieren :)

    Außerdem wird bei einem Update nicht erst die ganze Recordings-Liste gelöscht und komplett neu aufgebaut.

    Das gefällt mir gut, zusammen mit dem Patch für Multiple Recording-Verzeichnisse (http://www.vdr-portal.de/board…%C3%BCnschen/#post1177898) lohnt es sich dann richtig die Änderungen an der .update durch den VDR übers Netz weiterzureichen ohne dann man warten muss bis der VDR alles wieder befüllt hat :)


    Frohes Fest (ich bin dann auch mal weg...)

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

  • Moin!


    Hier funktioniert der Patch auch wunderbar. Ist ganz lustig, wenn man eine Aufnahme auf der Shell umbenennt und dann UPDR aufruft. Dann erscheint die Aufnahme unter dem neuen Namen im Menü und danach verschwindet die alte. :tup
    Das ist eine gute Idee, die Pointer zu "parken". Wenn sich ein Skin o.ä. nun einen Pointer auf ein cRecording-Objekt "eine Weile" merkt (während der Darstellung), dann sollte jetzt alles gut gehen.


    Wäre es denkbar, für vdr 2.1.x evtl. cRecording um eine Methode "HasVanished" zu erweitern? Dann können cRecording-Nutzer zwischendurch mal prüfen, ob's das Objekt noch gibt und es ggf. schnell vergessen.
    Ich hab jetzt aber noch keinen Anwendungsfall für sowas, ist nur eine Idee. Kann man später evtl. auch noch aufgreifen.


    Lars.

  • Ist ganz lustig, wenn man eine Aufnahme auf der Shell umbenennt und dann UPDR aufruft. Dann erscheint die Aufnahme unter dem neuen Namen im Menü und danach verschwindet die alte.


    Hmm, das ist vielleicht nicht ganz so toll.
    Vielleicht sollte ich es in cRecordings::ScanVideoDir() so machen, daß im Falle von 'initial == false' der 'state' erst ganz am Schluß inkrementiert wird...


    Zitat


    Das ist eine gute Idee, die Pointer zu "parken". Wenn sich ein Skin o.ä. nun einen Pointer auf ein cRecording-Objekt "eine Weile" merkt (während der Darstellung), dann sollte jetzt alles gut gehen.


    Ja, das sollte jetzt kein Problem mehr sein.


    Zitat


    Wäre es denkbar, für vdr 2.1.x evtl. cRecording um eine Methode "HasVanished" zu erweitern? Dann können cRecording-Nutzer zwischendurch mal prüfen, ob's das Objekt noch gibt und es ggf. schnell vergessen.
    Ich hab jetzt aber noch keinen Anwendungsfall für sowas, ist nur eine Idee. Kann man später evtl. auch noch aufgreifen.


    Ich würde auch sagen, daß wir das machen wenn es auch tatsächlich einen realistischen Anwendungsfall dafür gibt.


    Klaus

  • Das funktioniert bei mir noch nicht, es erscheint erst die neue, dann verschwindet die alte Aufnahme.
    Ich öffne das Aufnahmenmenü und navigiere in ein Verzeichnis mit drei Aufnahmen (drei Folgen einer Serie).
    Dann benenne ich in einer Shell ein Verzeichnis um (mv ... ...).
    Anschließend rufe ich "svdrpsend updr" auf. Dabei ist es egal, ob die umbenannte Aufnahme ausgewählt ist oder nicht.


    Ich schau mal, ob ich herausfinde, warum das so ist.


    Lars.

  • Ja, das ist mir auch gerade aufgefallen. Aber dann wird "ChangeState" doch nicht mehr aufgerufen, wenn ich eine Aufzeichnung einfach auf der Shell lösche, oder?
    Müsste das "DoChangeState" nicht zusätzlich bei der Rekursion mitgegeben werden, damit dann am Ende das "ChangeState" aufgerufen werden kann?


    EDIT: Oder man macht ein Feld draus.


    Lars.

  • So in der Art:

    Code
    class cRecordings : public cList<cRecording>, public cThread {
     private:
       static char *updateFileName;
       bool deleted;
       bool initial;
    +  bool doChangeState;
       time_t lastUpdate;


    Code
    void cRecordings::ScanVideoDir(const char *DirName, bool Foreground, int LinkLevel, int DirLevel)
     {
    +  if (DirLevel == 0)
    +     doChangeState = false;
    ...
    +  if (doChangeState && DirLevel == 0)
          ChangeState();
     }


    Lars.

  • Ja, da dachte ich auch dran. Das, was ich oben geschrieben hab, funktioniert zumindest schon mal (in meinem Fall).
    Ich probiere das mit dem Rückgabewert auch noch mal.


    Lars.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!