Compile Warnings in vnsiserver

  • Mit dieser Modifikation gibt es einen crash:

    Code
    Feb 13 17:48:23 vnas2.home.arpa vdr[30617]: [30660] VNSI: Requesting clients to reload channels list
    Feb 13 17:48:24 vnas2.home.arpa vdr[30617]: [32382] VNSI: Audio stream change, pid: 259, channels: 2, samplerate: 48000
    Feb 13 17:48:25 vnas2.home.arpa vdr[30617]: [32382] VNSI: Video stream change, pid: 255, width: 1920, height: 1080, aspect: 1,777778
    Feb 13 17:48:28 vnas2.home.arpa vdr[30617]: [30660] VNSI: Requesting clients to reload channels list
    Feb 13 17:48:28 vnas2.home.arpa runvdr.extreme[30617]: malloc(): unaligned tcache chunk detected


    aber leider keine Ausgabe von "cstring move"


    Timing scheint also ein Effekt zu haben.

  • So wie es aussieht scheint der Move-Operator/Constructor nicht die Ursache zu sein.

    Dazu wird er IMHO einfach zu oft aufgerufen, da müsste es auch anderswo krachen.

    Uns auch die Selbstzuweisung ist inzwischen ausgeschlossen.


    Auffällig ist, dass es vor dem Crash eine Änderung an der Kanalliste gab, auf die das Plugin gerade zugreift.

    Ist das Immer der Fall?


    Eigentlich sollte doch allein das korrekte setzen der Locks auf die Liste, die Zugriffe darauf threadsave machen?

    Und damit da eigentlich auch jegliche Timing-Effekte ausschließen.


    Auffällig ist aber halt, dass die Änderung der PIDs ziemlich direkt vor dem Crash kam.

    Fehler sehe ich da auch weder im Plugin, noch im VDR.

    Allenfalls diese Zeile in pat.c:

    847 StateKey.Remove(ChannelsModified);

    Was würde denn passieren, wenn ChannelsModified versehentlich false wäre, obwohl was geändert wurde?

    Das müsste man doch eigentlich testweise einfach mal auf true setzen können, ohne dass es eine Katastrophe gibt?


    Könnte es in diesem Fall was bringen die debug_locking zu aktivieren?

    (Zeile 29 thread.c)

    29 //#define DEBUG_LOCKING // uncomment this line to activate debug output for locking

    Gruss
    SHF


  • Im folgenden die gesamten Meldungen vor dem einzigen crash mit vdr-2.6.6 ohne Move-Operator/Constructor gestern Abend.


    Es war bisher bei allen Crashes die Sequenz:

    - changing PIDS/Channel etc.,

    - dann Requesting Clients to reload channel-list,

    - dann malloc


    zu sehen.


    Wie kann man diese Sequenz besser parametrisieren um die Vorgeschichte des crashes zu analysieren?



  • Und wenn das "writing 1 byte into a region of size 0 overflows the destination" ein Compilerfehler ist?

    Mit g++ 7.5.0 gibts lt. Post #8 den Fehler ja nicht.

    Aus Post #2:

    Code
    In file included from /usr/include/c++/13.2.1/bits/shared_ptr_atomic.h:33,
                     from /usr/include/c++/13.2.1/memory:81,
                     from videoinput.h:27,
                     from videoinput.c:27:
    In member function ‘std::__atomic_base<_IntTp>::__int_type std::__atomic_base<_IntTp>::load(std::memory_order) const [with _ITp = bool]’,

    Er macht dort ja noch nichts außer #include <memory> (OK, config.h hat er schon eingelesen)


    Kannst Du den kompletten VDR und Plugins mal mit g++ 7.5.0 und dessen Headerfiles compilieren und laufen lassen?

  • wirbel


    sorry ist ein copy and paste Problem, das Konsolenfenster war zu schmal. Korrekt lautet es:


    Code
    Feb 14 21:56:59 vnas2.home.arpa vdr[1987]: [1995] changing pids of channel 4269 (SWR RP HD) from 5121+5121=27:5122=deu@3,5123=mis@3,5127=qks@3;5126=deu@106:5135=deu:5134 to 5131+5131=27:5132=deu@3,5133=mis@3,5137=qks@3;5136=deu@106:5135=deu:5134
  • RHS kannst du den Vorschlag von SHF mal ausprobieren?

    SHF

    Wäre schon spannend zu wissen ob vor dem Crash auch Locking-Fehler geworfen werden.

  • Und wenn das "writing 1 byte into a region of size 0 overflows the destination" ein Compilerfehler ist?

    Da ist wohl wirklich ein Bug im GCC, aber im Sinne eines false positives:

    108374 – [12/13/14 Regression] unexpected -Wstringop-overflow when using std::atomic and std::shared_ptr

    In dem Fall geht es auch um weakPointer, sieht nahezu identisch aus.

    Ich hoffe die haben mit ihrer Einschätzung recht :schiel .


    Wobei das schon komisch wäre wenn Plugins, die da bisher keine Probleme hatten, jetzt Locking Fehler werfen.

    Wirkliche Fehler müssten jetzt schon im Log landen. Entsprechende Ausgaben sind jetzt schon aktiv und davon gibt es auch reichlich.


    Wenn muss es da was subtileres sein. Deshalb auch die Frage mit dem StateKey.Remove.

    Könnte es Probleme verursachen, wenn man was ändert und den state nicht inkrementiert?

    Ich bin da momentan nicht sicher, ob das was macht, oder nicht. So weit habe ich mich noch nicht "durch gebuddelt".


    Durch das DEBUG_LOCKING sollte man zumindest sehen, wann auf was Locks gesetzt werden, vielleicht sieht man dadurch irgendwelche Zusammenhänge.

    Momentan sieht man aus dem Log eigentlich nur, dass sich zwei VNSI-Clinets verbinden und dann kommt schon die Crash-Sequenz.

    Durch die Locks müsste man besser nachvollziehen können, worauf das Plugin zugreift.


    Man könnte auch mal probieren das Aktualisieren der Kanäle in VDR ganz ab zu stellen (setup.conf UpdateChannels = 0).

    Das wäre durchaus interessant, ob und wann es dann zum Absturz kommt.

    Wenn das Aktualisieren der PIDs die Ursache für den Absturz ist, sollte der dann nicht mehr auftreten.

    Wenn es an was anderem liegt, dann wo anders.

    Gruss
    SHF


  • Was passiert eigentlich mit den compiler warnings, wenn man einen check einfügt, ob der std::weak_ptr noch gültig ist?

    Ansonsten könnte in videoinput.c Zeilen 467 und 468 recv auf ein ungültiges object zeigen.


    videoinput.c:464 anstelle von

    Code
      // find an active receiver for the device
      for (auto p : s_Pool)
      {
        auto recv = p.lock();
        if (!recv->BeenDetached() && recv->Device() == device)
          return recv;
      }


    eher so, und im loop mit Referenz arbeiten um Kopien zu vermeiden.

    Code
      // find an active receiver for the device
      for (auto& p : s_Pool)
      {
        if (not p.expired()) {
           auto recv = p.lock();
           if (!recv->BeenDetached() && recv->Device() == device)
              return recv;
           }
      }
  • FireFly zu #65


    Ich habe es nochmal mit

    Code
    ++ (SUSE Linux) 7.5.0
    Copyright (C) 2017 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    übersetzt. Da gibt es keine Compiler Warnings und auch bisher kein crash bei normaler Nutzung mit zwei Clients seit 18h Server Laufzeit.

    Werde es weiter beobachten.


    Könnte mir jemand bei der Menge der Testvorschläge die Varianten etwas strukturieren, ich blicke derzeit nicht genau wie was mit einander wechselwirkt.


    Ich werde die neuen Tests dann mit diesen Compiler durchführen:

    Code
    g++-13 (SUSE Linux) 13.2.1 20240206 [revision 67ac78caf31f7cb3202177e6428a46d829b70f23]
    Copyright (C) 2023 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  • wirbel

    Habe deinen Vorschlag #70 mal eingebaut in videoinput.c insgesamt erhalte ich folgende Warnings in vnsiserver:

    Code
    g++ -g -O3 -Wall -march=native -Woverloaded-virtual -Wno-parentheses -fPIC -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -std=c++11 -c -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"vnsiserver"' -DVNSI_SERVER_VERSION='"1.8.3"' -I/usr/src/packages/BUILD/vdr-2.6.6-test/include -o responsepacket.o responsepacket.c
    streamer.c: In constructor ‘cLiveStreamer::cLiveStreamer(int, bool, int, uint8_t, uint32_t)’:
    streamer.c:57:17: warning: member ‘cLiveStreamer::m_Event’ is used uninitialized [-Wuninitialized]
       57 |  , m_VideoInput(m_Event)
          |                 ^~~~~~~

    und :

    Code
    g++ -g -O3 -Wall -march=native -Woverloaded-virtual -Wno-parentheses -fPIC -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -std=c++11 -c -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"vnsiserver"' -DVNSI_SERVER_VERSION='"1.8.3"' -I/usr/src/packages/BUILD/vdr-2.6.6-test/include -o status.o status.c
    channelfilter.c: In member function ‘void cVNSIChannelFilter::StoreWhitelist(bool)’:
    channelfilter.c:188:23: warning: loop variable ‘i’ creates a copy from type ‘const cVNSIProvider’ [-Wrange-loop-construct]
      188 |       for (const auto i : *whitelist)
          |                       ^
    channelfilter.c:188:23: note: use reference type to prevent copying
      188 |       for (const auto i : *whitelist)
          |                       ^
          |                       &


    und:

    diese sehen, glaub ich, leicht anders aus als vorher

  • Zitat

    //#define DEBUG_LOCKING // uncomment this line to activate debug output for locking

    Ich habe das DEBUG_LOCKING versuchsweise aktiviert, leider schreibt vdr mir dann den syslog mit lock/unlock Meldungen voll. Der crash ist so nicht weiter einzugrenzen.

  • Könnte mir jemand bei der Menge der Testvorschläge die Varianten etwas strukturieren, ich blicke derzeit nicht genau wie was mit einander wechselwirkt.

    So wirklich blickt hier wohl keiner durch was wie wechselwirkt, daher auch die vielen unterschiedlichen Testvorschläge um das Problem einzugrenzen.

    Ich werde es aber mal versuchen mit dem Stukturieren.


    Ausgangslage ist:

    VDR 2.6.6, GCC 7.5.0: keine Fehlermeldungen und keine Abstürze.

    VDR 2.6.6, GCC 13.2.1: Fehlermeldung und praktisch sofortiger Absturz.

    VDR 2.6.6, GCC 13.2.1 ohne Move-Operator/Constructor: Fehlermeldung und Abstürze, aber seltener.

    Richtig?


    Der Move-Operator/Constructor hat großen Einfluss auf die Speicherbelegung.

    Ohne entstehen durch die temporären Objekte, die gleich wieder gelöscht werden, viel mehr "Lücken".

    Das dürfte erklären, warum es ohne besser wird. Wenn man so eine "Lücke" nach dem problematischen Bereich liegt, fällt der Fehler nicht unbedingt auf.


    Zum weiteren Testen macht eigentlich nur die Version VDR 2.6.6, GCC 13.2.1 (mit Move-Operator/Constructor) Sinn, man will ja was sehen ;) .

    Es macht auch erstmal keinen Sinn die Tests zu kombinieren, das verwirrt einen nur, daher immer schön einzeln.


    Man könnte auch mal probieren das Aktualisieren der Kanäle in VDR ganz ab zu stellen (setup.conf UpdateChannels = 0).

    Der Test ist einfach, Änderungen am Code sind nicht nötig:

    Sicherstellen, dass ein Crash eintritt.

    VDR stoppen (wichtig!).

    setup.conf ändern.

    VDR starten und schauen, ob es erneut zum Crash kommt.


    Habe deinen Vorschlag #70 mal eingebaut in videoinput.c insgesamt erhalte ich folgende Warnings in vnsiserver:

    [...]

    diese sehen, glaub ich, leicht anders aus als vorher

    Der Test ist also erstmal schon erledigt.


    Die ersten zwei Warnungen sind neu, ich verstehe die aber noch nicht so ganz.

    Besonders die Zweite. Warum ist das erst jetzt ein Problem???


    Die Dritte sieht leicht anders aus, scheint aber der Ursprünglichen weitgehend zu entsprechen.

    Die Unterscheide können in den Compilereinstellungen liegen, die sind leicht unterschiedlich.




    Apropos Compilereinstellungen, da könnte man mal -O1 und -march=x86-64 (ist doch eine x86 64Bit CPU?) anstelle von -O3[tt] und -march=native[/tt] versuchen.

    Es könnte sein, dass der neue GCC es bei der Optimierung generell (-O_) etwas "übertreibt".

    -march=native erlaubt spezifischere Optimierungen für die verwendete CPU, da besteht die Chance, dass da Bugs drin stecken. Distributionen verwenden "x86-64" oder was vergleichbares, damit die Pakete allgemein kompatibel sind, native für exakt Deine CPU ist also wenig getestet.

    Auch wieder als frischer Test, ohne weitere Änderungen. Einfach schauen, ob es auch so auch crasht.


    Ich habe das DEBUG_LOCKING versuchsweise aktiviert, leider schreibt vdr mir dann den syslog mit lock/unlock Meldungen voll. Der crash ist so nicht weiter einzugrenzen.

    Dass da etwas mehr zusammen kommt, hatte ich schon erwartet. Das sind die Meldungen von allen Locks, Channels, Timers, EPG...

    Ich hatte nur die Hoffnung, dass es noch im Rahmen bleibt und der Syslog das bewältigt, das wäre übersichtlicher gewesen.

    Eine getrennte Logfile geht aber auch, wie Du das bei SUSE umleitest, musst Du aber selber mal schauen.


    Die (un)lock Meldungen sollten die pid/tid des verursachendem Prozesses enthalten.

    Diese sind auch in den Syslog-Meldungen enthalten:

    [...] vdr[1987]: [11772] VNSI Client[...] thread started (pid=1987, tid=11772, prio=high)

    [...] vdr[1987]: [1995] changing pids of channel 4[...]

    (Die 1987 ist die pid des VDR Hauptprozess.)

    So sollte man die Meldungen den Prozessen zuordnen können.

    (Die pids der channels haben damit übrigens gar nichts zu tun, heissen nur zufällig gleich.)


    Relevant sind wahrscheinlich auch nur die letzten 10-20 (un)locks vor dem Crash.

    Also etwa ab dem changing pids evtl noch ein paar davor.

    Gruss
    SHF


  • SHF danke für deine Hilfe bei der Beschreibung der Testschritte.


    Zunächst : mein Server läuft auf einem Asrock ITX5040 Mainboard also x86_64, 16GB Memory, LAN 2,5 GB r8125 über minipcie adapter,

    System auf NVME 2TB, ansonsten 3x 2,5" 5TB Platten für NAS (nextcloud), Asterisk, FHEM etc. also 24h/7T Home Server Betrieb. ca.10W Dauerleistung.


    DVB besteht aus 1 x DIGIBIT 4Tuner Sat und 2 x Fritz Repeater DVB-C (je 2 DVB-C Tuner) also 4 DVB-S . 4 DVB-C Tuner.

    PLUGINS: Live, dvbapi, SATIP u. VNSISERVER also Headless Betrieb.


    In meiner Ausgangslage ist UpdateChannels = 5.


    Ich werde dies mal mit DEBUG_LOCKING und meinen normalen Compilereinstellungen versuchen. Melde mich, wenn es was gibt.

  • VDR 2.6.6, GCC 11.1.0: keine Warnungen beim compilieren

    VDR 2.6.6, GCC 13.2.0: Warnungen beim compilieren


    Ich hab gestern mal gcc neu compiliert, spätestens ab 13.2.0 tauchen die Warnungen auf.

  • Ich hab noch diesen Compiler auf dem System:


    Code
    g++ (SUSE Linux) 12.3.0
    Copyright (C) 2022 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    auch damit gibt es 3 VNSISERVER Warnungen:


    Code
    g++ -g -O3 -Wall -march=native -Woverloaded-virtual -Wno-parentheses -fPIC -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -std=c++11 -c -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"vnsiserver"' -DVNSI_SERVER_VERSION='"1.8.3"' -I/usr/src/packages/BUILD/vdr-2.6.6-test/include -o responsepacket.o responsepacket.c
    streamer.c: In constructor ‘cLiveStreamer::cLiveStreamer(int, bool, int, uint8_t, uint32_t)’:
    streamer.c:57:17: warning: member ‘cLiveStreamer::m_Event’ is used uninitialized [-Wuninitialized]
       57 |  , m_VideoInput(m_Event)
          |                 ^~~~~~~


    Code
    g++ -g -O3 -Wall -march=native -Woverloaded-virtual -Wno-parentheses -fPIC -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -std=c++11 -c -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"vnsiserver"' -DVNSI_SERVER_VERSION='"1.8.3"' -I/usr/src/packages/BUILD/vdr-2.6.6-test/include -o status.o status.c
    channelfilter.c: In member function ‘void cVNSIChannelFilter::StoreWhitelist(bool)’:
    channelfilter.c:188:23: warning: loop variable ‘i’ creates a copy from type ‘const cVNSIProvider’ [-Wrange-loop-construct]
      188 |       for (const auto i : *whitelist)
          |                       ^
    channelfilter.c:188:23: note: use reference type to prevent copying
      188 |       for (const auto i : *whitelist)
          |                       ^
          |                       &

    und

    Also auch g++ 12.3.0 hat schon Warnings,

    interessant wird das ganze wenn man mit diesen Compiler und wie oben angeregt mit -O1 und -march=x86-64 übersetzt ändern sich die Dateien in denen die Warnings auftreten:



    also einmal:

    responsepacket.c, status.c,vnsisocket.c


    und dann;


    hash.c vnsitimer.c, vnsisocket.c :wow

  • Damit kann das Problem weiter eingeengt werden

    gcc > 11.1.0 && gcc <= 12.3.0

  • Damit kann das Problem weiter eingeengt werden

    gcc > 11.1.0 && gcc <= 12.3.0

    Wenn man nach diesen Warnungen sucht, findet man auch immer, dass die mit dem 12er Zweig, also 12.0.0 anfingen. Von daher deckt sich das.

    Im Changelog steht auch zu einigen der Warnungen, dass die "optimiert" wurden. Aber das sind ja letztendlich lediglich Hinweise, dass da was seien könnte und bislang hat es ja so funktioniert.

    Einen echten Grund, warum es aber diese Probleme gibt, habe ich beim überfliegen nicht gesehen.

    Vielleicht sieht ja jemand anderes mehr.


    responsepacket.c, status.c,vnsisocket.c


    und dann;


    hash.c vnsitimer.c, vnsisocket.c

    Letztendlich sind es aber immer die 3 gleichen Stellen, die die Warnung auslösen.

    Das deutet stark darauf hin, dass die dem GCC nicht gefallen.


    Warum das von unterschiedlichen Dateien getriggert wird, weiß der Geier.

    Eventuell liegt es einfach an der Reihenfolge der Bearbeitung?


    Interessant ist auch, dass die Änderung aus #70 anscheinend keinen Einfluss hatte.


    Code
    streamer.c: In constructor ‘cLiveStreamer::cLiveStreamer(int, bool, int, uint8_t, uint32_t)’:
    streamer.c:57:17: warning: member ‘cLiveStreamer::m_Event’ is used uninitialized [-Wuninitialized]
       57 |  , m_VideoInput(m_Event)
          |                 ^~~~~~~

    Zu -Wuninitialized steht was im Changelog (s.o.).

    An der Warnung könnte prinzipiell was dran sein, uninitialisierte Variablen/Objekte können derartige Abstürze auslösen.

    Die Warnung warnt auch vor allen möglichen potenziellen Problemen, die aber nicht auftreten müssen, wenn man es richtig macht.

    Und da es bislang ja funktioniert hat ...


    Neu ist in GCC 12 übrigens dieses Stück in der Dokumentation dazu:

    Zitat

    In C++, this warning also warns about using uninitialized objects in member-initializer-lists. For example, GCC warns about b being uninitialized in the following snippet:

    Code
    struct A {
      int a;
      int b;
      A() : a(b) { }
    };


    Code
    channelfilter.c: In member function ‘void cVNSIChannelFilter::StoreWhitelist(bool)’:
    channelfilter.c:188:23: warning: loop variable ‘i’ creates a copy from type ‘const cVNSIProvider’ [-Wrange-loop-construct]
      188 |       for (const auto i : *whitelist)
          |                       ^
    channelfilter.c:188:23: note: use reference type to prevent copying
      188 |       for (const auto i : *whitelist)
          |                       ^
          |                       &

    Irgendwie sieht es mir so aus, als ob das ein beliebter Anfänger/Flüchtigkeitsfehler ist.

    Die neue (ich habe noch C++2003 gelernt) Syntax mit dem "auto" ist zwar schön kompakt, was IMHO aber zu so Fehlern einlädt. Das fehlende "&" übersieht man einfach gerne mal.

    Daher wohl die Warnung.


    Die Kopie ist, von der Performance, Spericherverbrauch, ... zwar nicht ideal, ein wirkliches Problem dürfte das in den meisten Fällen aber wohl nicht auslösen, denke ich.


    Und in unserem Fall bin ich momentan nicht mal sicher, ob das nicht Absicht so war.



    Den letzten von den Fehlern hatten wir ja schon und da wird da wird behauptet, dass es ein "false positive" ist.

    Gruss
    SHF


Jetzt mitmachen!

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