Deadlock bei Aufnahme auf letztverfügbarem Gerät mit Umschalten

  • Ja, leider.Und jetzt habe ich ein zweites Mal darüber nachgedacht und fürchte, der Erkenntnisgewinn wird sich in Grenzen halten. Das es mit einem CamSlot->Assign(NULL) ohne Wartezeit funktioniert hat dein Versuch ohne LOCK_THREAD ja schon gezeigt.

    Gibt es das Problem ohne MTD auch (bei den camtweaks-Flags 0x4 dazunehmen) ?

    Helmut

  • Der der VDR um 20:00 mit Umschalttimer (ohne VDR-2.5 Patch, abgesehen TS-Errors, mit original LOCK_THREAD) an seiner neuen Lieblingsstelle pausierte, hab ich den Patch oben kurz eingespielt:

    Beim Retune hat es dann das CAM abgeschossen, aber der VDR hing nicht.

    Im Debugger sah man so nichts. Mit "c" nach automatischem Modulreset ging es dann weiter.

    Debugger ist noch attached, gucke gegen 22:00, was bei einem Umschalttimer regulär passiert...


    Edit:

    CAM mag das gar nicht, VDR läuft weiter.


    Am MTD (0x4) sollte es eigentlich nicht liegen, da ich den Deadlock auch mit FTA Programmen erzeugen kann. Aber wird probiert:


    Edit 2:

    Mit 6 Umschaltaufnahmen (FTA <-> FTA, 1x laufend über CAM) kam der Fehler nicht (LOCK_THREAD original), aber immer tut er das auch nicht (CAMTweaks = 0x827 statt 0x823).


    Edit 3:

    Bin erst einmal wieder auf

    und CAM-Tweaks 0x823 zurück.


    Bisher führte zu häufiges Umschlten auf CAM-Programmen dazu, daß irgendwann nur noch eine von zwei möglichen Entschlüsselungen verfügbar war. Jetzt machte das CAM nach 24x schnellem Umschalten während einer Aufnahme (über das CAM) einen Reset (CI+ Auth) und weiter geht's.



    Stefan

  • Vielleicht kommt der Deadlock von cDevice::DetachAllReceivers.

    Wenn Thread 1 bereits hier den Lock auf mutexReceiver hält, wird er in cDevice::Detach() nicht freigegeben. Und damit würde der Thread 41 in cDevice::Action() nicht aus der for-Schleife herauskommen und das Unlock() am Ende von while(Running() nie stattfinden.

    Kommentiere einmal die MuteLock Zeile() in DetachAllReceivers aus.

    Code
    1. void cDevice::DetachAllReceivers(void)
    2. {
    3. // cMutexLock MutexLock(&mutexReceiver); <<------- hier
    4. for (int i = 0; i < MAXRECEIVERS; i++)
    5. Detach(receiver[i]);
    6. }

    Ich frage mich allerdings, wieso dann ein normales Umschalten von einem verschlüsseltem Sender funktioniert. Veilleichts liegt es an DDCI2.

    Helmut

  • Mit der auskommentierten Zeile habe ich es jetzt noch nicht geschafft, einen Deadlock zu erzeugen.

    Einmal hat das Modul in die bereits laufende Aufnahme ein paar Backref-Fehler gemacht, einmal die neue Aufnahme mit #750 TS-Fehler begonnen, bevor Bild kam. Aber kein Hänger mehr.


    Seiteneffekt bisher (Kurztest, klar) nicht zu endecken. Habe aber auch nur zwei Tuner.


    Stefan

  • Dann bin ich ziemlich sicher, dass der Deadlock hier ausgelöst wurde. Da durch DetachAllReceivers() alle Receiver auf "NULL" gesetzt werden, ist hier ein Lock auf die Receiverliste vermutlich auch nicht so wichtig.


    Backref-Fehler sagt mir jetzt nichts. Die 750 TS-Fehler zu Beginn sind unverschlüsselten Pakete die man bei einem Programmwechsel zwangsläufig erhält. Es dauert etwas bis die erste ECM empfangen wird und das Modul mit der Entschlüsselung beginnen kann. Das ist im Live Modus nicht anders, ein Bild gibt es erst mit entschlüsselten TS-Paketen.


    LG Helmut

  • Hatte angenommen, fehlende ECM (hier NDS alle 7 sec, ~ 300 ms vor Gültigkeit - falls das noch aktuell ist), würden als Scrambled im Log ankommen, aber stimmt, dann kommt nix, nur Modul abschießen macht "scrambled"-Fehler.


    Backref: dies hier

    Ich stopfe das ins VDR-Log, und gucke bei Fehlern schon mal nach, was Ursache war.


    Stefan

  • Da durch DetachAllReceivers() alle Receiver auf "NULL" gesetzt werden, ist hier ein Lock auf die Receiverliste vermutlich auch nicht so wichtig.

    Der mutexReceiver schützt die Liste der Receiver des Devices, sollte also bei jedem Zugriff gelockt werden. Den Lock in DetachAllReceivers() wegzulassen fühlt sich irgendwie nicht richtig an. Was wäre z.B. wenn die Schleife receiver[i] "nimmt" und bevor sie Detach() damit aufrufen kann von anderer Stelle ein explizites Detach() mit diesem Receiver gemacht (und der Receiver gelöscht) wird? Ich weiß nicht, wie wahrscheinlich dieses und andere Szenarien sind, aber den Lock hier wegzulassen würde mir Bauchschmerzen machen...

  • kls mit "nicht so wichtig", meinte ich eher, ein Weglassen des Lock auf mutexReceiver in DetachAllReceivers() hat wahrscheinlch weniger Nebenwirkungen als das auf den Device-mutex in SetCamSlot().

    Der Aufruf von Detach() kann nur von außerhalb des "großen" mutexReceiver-Lock stattfinden. Wie wäre es, innerhalb eines kurzen Lock die *Receiver in ein lokale Kopie auzulesen und nach dem Lock das Detach() über die Kopie aufzurufen.

    So in etwa:

    LG Helmut

  • Mein Vorschlag von zuvor hat ein anderes Problem - die lokale Kopie der Receiverliste kann nach dem Lock schnell veraltet sein. Das ist eigentlich auch nicht viel besser als ganz ohne Lock.

    Wenn andere Threads die Receiverliste nur lesen ist es ja kein Problem, er wer könnte die Liste zeitgleich noch verändern wollen?

    Helmut

  • Da der Deadlock nur wegen camSlot->Assign() entsteht, könnte man das in Detach() auch nur bedingt machen. Dann kann der große MutexLock(&mutexReceiver) bleiben.

    LG Helmut

  • Vielleicht eine Erklärung, warum dieser Deadlock nicht schon häufiger festgestellt wurde.
    Die Vorrausetzungen sind: Live auf verschlüsseltem Sender mit dem einzigen Device das für eine Aufnahme zur Verfügung steht, ein Aufnahme-Timer für ein Programm auf einem anderen Transponder und zum Zeitpunkt des Timer-Start muss auch tatsächlich das Live-Progarmm aktiv sein.


    Die letzte Punkt ist der Interessante:


    Der VDR will sicherstellen, das zum Zeitpunkt der Aufnahme ein Device tasächlich zur betriebsbereit ist. Dazu wird innerhalb der Timervorlaufzeit TIMERLOOKAHEADTIME schon ein Device ausgewählt und mit diesem auf den Transponder getuned - aber nicht im "Liveview" Modus sondern nur mit IDLE-Priority. Da es sich dabei um das Device mit den verschlüsselten Live-Programm handelt, wird dabei auch der CamSlot entfernt.


    Der VDR main-Loop will aber immer einen Progarmm darstellen, also wird nach kurzer Zeit wieder auf das Live Programm zurückgeschalten. Das ganze wiederholt sich innerhalb der Timervorlaufzeit TIMERLOOKAHEADTIME einige Male.


    Für den Deadlock ist entscheidend, welcher der beiden Zustände beim Timer-Start tatsächlich aktiv ist. Beim Live-Programm kommt ein Deadlock, beim Idle-Programm nicht.

    Da insgesamt länger auf dem Idle-Transponder getuned ist, ist die Wahrscheinlichkeit eines Deadlock geringer als die einer erfolgreichen Aufnahme. Ich musste für zwei Deadlocks 6 Timer Programmieren.


    Hier ein paar Zeilen aus dem syslog. 2min. Vorlaufzeit Setup.VpsMargin, Live ist "3sat HD", Aufnahme um 22:10 auf "ORF1 HD" - in diesem Fall kein Deadlock weil unmittelbar davor auf richtigen Transponder und ohne camslot getuned wird.


    Helmut


    Was mir auffällt: dieses 2 Minuten lange Hin- und Herschalten sieht eigentlich nicht besonders gut aus :).

  • Also bisher funktioniert Dein letzter Patch ... Danke :)


    Das 2 minütige Hin- und Herschalten macht das "VPS" schon immer.

    Bei "normalen" Timer-Aufnahmen passiert das nur unsichtbar auf freien Karten.


    VPS ist bei mir wegen epg2vdr aus, sonst brechen die Aufnahmen ab, sobald sie in der Datenbank sind.

    Muß dem Plugin mal abgewöhnen, an aktiven VPS Timern rumzutogglen.


    Stefan

  • Fourty2 : Ich habe es mit dem Patch gestern nicht mehr getestet, aber gut wenn du es bestätigen kannst.

    Eine kleine Richtigstellung: Es ist natürlich nicht die Timervorlaufzeit sondern TIMERLOOKAHEADTIME (60s) bzw. Setup.VpsMargin (bei mir 120s) innerhalb der auf den Transponder der kommenden Aufnahme geschalten wird. Ich habe es in meinem Post richtiggestellt.

    Helmut