[gelöst] VDR 2.3.9 hängt bei der Wiedergabe von Aufnahmen mit rpihddevice

  • Hallo,

    ich habe den VDR 2.3.9 auf einem Raspberry Pi 2 unter Arch Linux ARM ausprobiert - LiveTV über das streamdev-client Plugin funktioniert, aber bei der Wiedergabe von Aufnahmen (egal ob von der SD-Karte oder über NFS) hängt sich der VDR weg.

    Im Log sieht man nur, dass ein i/o throttle aktiv wird und der Buffer voll läuft. Der VDR ist dann unbedienbar, bis der Watchdoch zuschlägt. Neben dem streamdev-client ist nur das rpihddevice-Plugin aktiv. Der VDR wurde zur Ursachenforschung ohne Patches gebaut.

    Laut htop hat die CPU währenddessen kaum etwas zu tun.


    Ich hatte versuchsweise #define USE_FADVISE_READ = 1 in die tools.c eingebaut, das hat nichts am Verhalten geändert. Mit dem VDR 2.3.8 hatte ich das Problem noch nicht. Auf dem Testrechner für Ubuntu 18.04 und VDR 2.3.9 klappt die Wiedergabe von Aufnahmen mit softhddevice über VDPAU.


    Wie kann man dem Problem am besten auf die Spur kommen?

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

  • Ich verwende, seit mein betagter Wohnzimmer-VDR mit der TT-S2 6400 den Geist aufgegeben hat (wohl ein Motherboard-Defekt), auch einen Raspberry Pi 2 als Client, und die Wiedergabe funktioniert damit einwandfrei.

    Allerdings verwende ich nicht das streamdev-client-Plugin.

    Tritt das Problem bei jedem Wiedergabeversuch auf?

    Passiert es auch ohne streamdev-client?


    Klaus

  • Der Hänger tritt bei allen Wiedergabeversuchen reproduzierbar auf.


    Es scheint tatsächlich am streamdev-client zu liegen. Wenn ich das Plugin deaktiviere und dann einen Sundtek-Stick übers Netzwerk mounte (der Treiber legt dann lokal ein DVB-Device dafür an) , klappt die Wiedergabe von Aufnahmen ohne Probleme.

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

    Dieser Beitrag wurde bereits 1 Mal editiert, zuletzt von seahawk1986 ()

  • Von 2.3.8 auf 2.3.9 wurde am Locking noch einiges geändert, um Deadlocks zu vermeiden. Anscheinend "leidet" da jetzt streamdev-client darunter. VDR hängt ja anscheinend irgendwo in der Hauptschleife. Kannst du da bitte mal Testausgaben einbauen um evtl. herauszufinden, wo er da feststeckt? Oder während er hängt den Debugger anklemmen und einen Backtrace aller Threads machen.


    Klaus

  • Ich habe mich mal mit gdb an den hängen VDR-Prozess gehängt, ein SIGINT gesendet und dann thread apply bt und thread apply bt full laufen lassen. Das Ergebnis habe ich angehängt.

    Dateien

    • vdr-dbg.txt

      (29,14 kB, 30 Mal heruntergeladen, zuletzt: )

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

  • Zitat

    Backtrace stopped: previous frame identical to this frame (corrupt stack?)

    Irgendwie scheint das Ganze zu dem Zeitpunkt nicht mehr ganz "gesund" zu sein...

    Ich sehe auch nicht wirklich etwas, das mir einen Hinweis auf die Stelle gibt, wo es hängt.


    Bleibt wohl doch nur, in der Hauptschleife Ausgaben einzubauen und sukzessive zu verfeinern, um rauszukriegen, wo er hängenbleibt.


    Klaus

  • In der vdr.c kommt er bis Zeile 1412, das ist der Aufruf von cControl::Shutdown(). In der player.c kommt er bis Zeile 105:

    Code: player.c
    1. void cControl::Shutdown(void)
    2. { printf("calling cControl::Shutdown() player.c:101\n");
    3. cMutexLock MutexLock(&mutex); printf("created cMutexLock in cControl::Shutdown() player.c:102\n");
    4. cControl *c = control; /* avoids recursions */ printf("created cControl *c in cControl::Shutdown() player.c:103\n");
    5. control = NULL; printf("set control = NULL in cControl::Shutdown() player.c:104\n");
    6. delete c; printf("leaving cControl::Shutdown() player.c:105\n");
    7. }

    Auf stdout sieht man dann beim Abspielen einer Aufnahme vor dem Hänger:

    Code
    1. calling cControl::Shutdown() player.c:101
    2. created cMutexLock in cControl::Shutdown() player.c:102
    3. created cControl *c in cControl::Shutdown() player.c:103
    4. set control = NULL in cControl::Shutdown() player.c:104

    Also hängt er in Zeile 105 bei delete c;. Wenn ich das entferne (also im Original Zeile 105 auskommentiere), gibt es keinen Hänger mehr und die Aufnahme wird abgespielt - verstehe ich das richtig, dass damit nicht der Pointer selbst, sondern der Speicherbereich gelöscht werden soll, auf den er zeigt?

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

    Dieser Beitrag wurde bereits 1 Mal editiert, zuletzt von seahawk1986 ()

  • Ich habe die Zeile 100 ff. in der player.c mal noch um eine Address-Angabe für den Pointer c erweitert:

    Code: player.c
    1. void cControl::Shutdown(void)
    2. { printf("calling cControl::Shutdown() player.c:101\n");
    3. cMutexLock MutexLock(&mutex); printf("created cMutexLock in cControl::Shutdown() player.c:102\n");
    4. cControl *c = control; /* avoids recursions */ printf("creating cControl *c in cControl::Shutdown() player.c:103\n");
    5. control = NULL; printf("setting control = NULL in cControl::Shutdown() player.c:104\n");
    6. printf("Address of c is %p\n", (void *)c); delete c; printf("leaving cControl::Shutdown() player.c:105\n");
    7. }

    Das sieht dann z.B. so aus:

    Code
    1. calling cControl::Shutdown() player.c:101
    2. created cMutexLock in cControl::Shutdown() player.c:102
    3. creating cControl *c in cControl::Shutdown() player.c:103
    4. setting control = NULL in cControl::Shutdown() player.c:104
    5. Address of c is 0x959598

    Wenn ich mich dann mit gdb an den hängenden VDR-Prozess attache, bekomme ich für das cControl-Objekt:

    Code
    1. gdb ./vdr $(pidof vdr)
    2. [...]p
    3. (gdb) p *(cControl *) 0x959598
    4. $2 = {<cOsdObject> = {_vptr.cOsdObject = 0x631cc0 <vtable for cTransferControl+8>, isMenu = false, needsFastResponse = false}, static control = 0x0, static mutex = {mutex = {__data = {__lock = 1, __count = 0, __owner = 11773,
    5. __kind = 2, __nusers = 1, {__spins = 0, __list = {__next = 0x0}}}, __size = "\001\000\000\000\000\000\000\000\375-\000\000\002\000\000\000\001\000\000\000\000\000\000", __align = 1}, locked = 1}, attached = true,
    6. hidden = true, player = 0x9596e8}

    Hält das da selbst noch einen Mutex?

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

  • Du siehst ja im mutex die Pid vom owner, der hält den Lock

    vdr-2.4.0
    softhddevice, chanman, cdda, dbus2vdr, dvd, dynamite, epgsearch, femon, filebrowser, graphlcd, graphtftng,
    menuorg, osdteletext, radio, recsearch, streamdev-server, vdrmanager, vnsiserver

    linux-3.13.0 M3N78-VM (Nvidia 8200) CIne CT-V7 DVB-C
    yavdr-0.6 als Basis mit vielen Änderungen

  • 11773 war laut gdb der Thread #1, also nach meine Verständnis der Thread mit der VDR Hauptschleife.


    Ich bin bei C++ und Multithreading ziemlich blutiger Anfänger und wäre froh, wenn mir da jemand beim Debuggen helfen könnte.

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

  • Du könntest dich mit gdb an den hängenden vdr anschliessen und mit "generate-core-file" einen kompletten core im Arbeitsverzeichnis erzeugen. Dann sind hoffentlich die Stacks komplett und man kann die Aufrufreihenfolge untersuchen.

    vdr-2.4.0
    softhddevice, chanman, cdda, dbus2vdr, dvd, dynamite, epgsearch, femon, filebrowser, graphlcd, graphtftng,
    menuorg, osdteletext, radio, recsearch, streamdev-server, vdrmanager, vnsiserver

    linux-3.13.0 M3N78-VM (Nvidia 8200) CIne CT-V7 DVB-C
    yavdr-0.6 als Basis mit vielen Änderungen

  • Ok, dann sehe ich für c die Addresse 0x69646b00 und diese Threads:

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

  • yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

  • Leider ist beim main thread kein Aufrufer vom Lock zu sehen. Ich verstehe den Zusammenhang mit streamdev noch nicht (der client macht am vdr nur live-TV?).

    vdr-2.4.0
    softhddevice, chanman, cdda, dbus2vdr, dvd, dynamite, epgsearch, femon, filebrowser, graphlcd, graphtftng,
    menuorg, osdteletext, radio, recsearch, streamdev-server, vdrmanager, vnsiserver

    linux-3.13.0 M3N78-VM (Nvidia 8200) CIne CT-V7 DVB-C
    yavdr-0.6 als Basis mit vielen Änderungen

  • Ich verstehe den Zusammenhang mit streamdev noch nicht (der client macht am vdr nur live-TV?).

    Den Deadlock kann ich immer dann reproduzierbar auslösen, wenn streamdev-client beim Versuch eine Aufnahme wiederzugeben mit dem streamdev-server verbunden ist und einen Kanal empfängt.


    Die Einträge für das Plugin in der setup.conf sehen so aus - damit sollte das Plugin sich nur um Live-TV kümmern und sich keine EPG-Infos oder ähnliches aus dem Stream holen:

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

  • Ich habe den VDR mal statt mit -g O3 mit -g -Og gebaut, damit sieht man etwas mehr - hilft das weiter?

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

  • yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)

  • Das funktioniert bei mir ohne Probleme, habe allerdings auch keinen rpi.

    vdr-2.4.0
    softhddevice, chanman, cdda, dbus2vdr, dvd, dynamite, epgsearch, femon, filebrowser, graphlcd, graphtftng,
    menuorg, osdteletext, radio, recsearch, streamdev-server, vdrmanager, vnsiserver

    linux-3.13.0 M3N78-VM (Nvidia 8200) CIne CT-V7 DVB-C
    yavdr-0.6 als Basis mit vielen Änderungen

  • Es gab ja schon mal ein Problem mit einem Patch für vdr-2.3.8 und streamdev. (Wo das Raspberry Pi auch besonders anfällig für war)

    Streamdev Client/Server + CI Modul = Glückspiel ?


    Da hat Klaus mir den Tip gegeben im Streamdev client (/client/device.c)


    Code
    1. LOCK_THREAD;

    in cStreamdevDevice::SetPid() auszukommentieren, was auch geholfen hat


    Vielleicht liegt hier das Problem in "void cStreamdevDevice::CloseDvr(void)"

  • Danke für den Hinweis, damit ist der Deadlock weg:

    Eine Änderung in "void cStreamdevDevice::CloseDvr(void)" scheint nicht nötig zu sein,

    yaVDR-Dokumentation (Ceterum censeo enchiridia esse lectitanda.)