Destruktor mit Mutex



  • Ich verwende die boost::threads und somit auch die Mutexe. Eine meiner Klassen sieht so aus:

    class DatenModul
    {
      public:
        DatenModul(int);
        ~DatenModul();
        ...
    
      private:
        ...
    
        // Mutexe für die Datenstrukturen
        boost::shared_mutex DatenZuModulListeMutex;
        boost::shared_mutex ModulListeMutex;
    };
    

    Die Mutexe verwende ich dann in der cpp:

    boost::unique_lock<boost::shared_mutex> lock(ModulListeMutex);
      boost::shared_lock<boost::shared_mutex> lock(ModulListeMutex);
    

    Wenn ein Objekt dieser Klasse wieder vernichtet wird bekomme ich einen Fehler:

    /usr/include/boost/thread/pthread/mutex.hpp:50: void boost::mutex::lock(): Assertion `!pthread_mutex_lock(&m)' failed.
    Aborted

    Laut google hat das damit zu tun, dass ein Mutex nicht unlocked wurde. Deshalb hab ich mir nun einen Destruktor geschrieben, aber der löst das Problem auch nicht 😞

    DatenModul::~DatenModul()
    {
      ModulListeMutex.unlock();
      DatenZuModulListeMutex.unlock();
    };
    

    Kann mir jemand sagen warum? Vielen Dank schonmal im Voraus!



  • fabske schrieb:

    Wenn ein Objekt dieser Klasse wieder vernichtet wird bekomme ich einen Fehler:

    /usr/include/boost/thread/pthread/mutex.hpp:50: void boost::mutex::lock(): Assertion `!pthread_mutex_lock(&m)' failed.
    Aborted

    Die Assertion erscheint nicht beim Löschen des Mutex sondern beim Locken desselben. Es ist also zu vermuten, dass der Code im Destruktor von DatenModul (oder einem Caller von diesem) direkt oder indirekt eines der beiden Mutexe zum zweitenmal im selben Thread locked. Da es sich um kein recursive_mutex handelt, ist das zweimalige Locken nicht zulässig.

    Gruß
    Werner



  • Hallo Werner! Da hast du Recht. In der Tat wird ein DatenModul von der main erzeugt, nach Bedarf vernichtet und ein neues erzeugt. Aber mit dem beschrieben Destruktor sollte das doch kein Problem sein oder? Die Mutexe sind doch dann unlocked?



  • Hallo Werner und andere. Ich hoffe ihr könnte mir helfen, denn ich komm nicht weiter. 😞 Ich hab die Vernichtung des DatenModuls nun mal auskommentiert, weil ich einfach nicht weiß was da los ist.

    Genau der gleiche Fehler tritt noch an einer anderen Stelle auf! Das DatenModul hat eine Funktion abfragenModul():

    std::string DatenModul::abfragenModul(boost::thread::id ID)
    {
      std::map< boost::thread::id, Modul* >::iterator i;
    
      boost::shared_lock<boost::shared_mutex> lock(ModulListeMutex);
      i = ModuleListe.find(ID);
    
      if( i==ModuleListe.end() ) return "NICHT GEFUNDEN!";
      else return i->second->Modulname;
    
    };
    

    Das HIRN Modul hat eine Funktion, welche die abfragenModul aufruft (wenn DEBUG übersetzt wird):

    bool HIRN::einfuegen(Daten* Objekt)
    {
      boost::unique_lock<boost::shared_mutex> lock2(NeuRausMutex); 
      boost::unique_lock<boost::shared_mutex> lock1(AltReinMutex); 
    
      if( AltRein.empty() )
      {
        #ifdef DEBUG
          std::stringstream ausgabe;
          ausgabe << D->abfragenModul(boost::this_thread::get_id()) << " hat einfuegen(" << Objekt->leseErstellungszeit() << " | " << Objekt->leseBenutzung() << ") aufgerufen: AltRein ist leer";
          HIRN::schreiben(ausgabe.str());
        #endif
    
        NeuRaus.push_back(Objekt);
        NeueDaten.notify_all();
      }
    ...
    

    Wenn ich nun aus dem HIRN heraus die einfuegen() aufrufe, gibt es einen Fehler:

    HIRN1_DEBUG: /usr/include/boost/thread/pthread/mutex.hpp:50: void boost::mutex::lock(): Assertion `!pthread_mutex_lock(&m)' failed.
    Aborted
    

    Ich hab jetzt Stunden lang gesucht, aber ich komm nicht drauf was los ist. Wenn ich in der abfragenModul() die Zeile

    boost::shared_lock<boost::shared_mutex> lock(ModulListeMutex);
    

    auskommentiere gibt es einen Segmentation fault. Aber wieso?

    Wenn ich aus der HIRN heraus die einfuegen() nicht aufrufe und stattdessen testweise einfach mal direkt

    D->abfragenModul(boost::this_thread::get_id());
    

    , klappt das wunderbar. Es scheint nur die Kombination von einfuegen() und abfragenModul() zu sein :(.



  • Also ich hab hier echt ein großes Problem und verstehe gar nichts. Früher hat diese Funktion wunderbar funktioniert (tolles Wortspiel 😉 ) und seit neuestem geht sie nicht mehr.

    Ich hab nun eine ähnliche Funktion erstellt, die ich ebenfalls brauche, aber auch diese macht Ärger!

    // Hiermit kann man ein thread::id der besseren Lesbarkeit halber zu einem Modulnamen auflösen
    std::string DatenModul::abfragenModul(boost::thread::id ID)
    {
      std::map< boost::thread::id, Modul* >::iterator i;
    
      boost::shared_lock<boost::shared_mutex> lock(ModulListeMutex);
      i = ModuleListe.find(ID);
    
      if( i==ModuleListe.end() ) return "NICHT GEFUNDEN!";
      else return i->second->Modulname;
    };
    
    // Hiermit kann man zu einer thread::id einen Zeiger auf das entsprechende Modul bekommen
    Modul* DatenModul::abfragenModulZeiger(boost::thread::id ID)
    {
      std::map< boost::thread::id, Modul* >::iterator i;
    
      boost::shared_lock<boost::shared_mutex> lock(ModulListeMutex);
      HIRN::schreiben("AAA");
      i = ModuleListe.find(ID);
    
      if( i==ModuleListe.end() )
      {
        return NULL;
      }
      else
      {
        return i->second;
      }
    };
    

    Es ist genau diese Zeile bei der ich zur Ausführung einen Segmentation fault bekomme:

    boost::shared_lock<boost::shared_mutex> lock(ModulListeMutex);
    

    Vielleicht nützt die Klassendefinition was:

    class DatenModul
    {
      public:
        DatenModul(int);
        ~DatenModul();
        void anmeldenModul(Modul*);
        void eintragenDaten(std::string);
        Modul* abfragenDaten(std::string);
        std::string abfragenModul(boost::thread::id);
        Modul* abfragenModulZeiger(boost::thread::id);
        bool bereit();
    
      private:
        // Datenstruktur zum Verwalten von Modulen
        std::map< boost::thread::id, Modul* > ModuleListe;
        // Datenstruktur zur Zuordnung von Daten zu Modulen
        std::map< std::string, boost::thread::id > DatenZuModulListe;
    
        int AnzahlModule;
        int bereiteModule;
    
        // Mutexe für die Datenstrukturen
        boost::shared_mutex DatenZuModulListeMutex;
        boost::shared_mutex ModulListeMutex;
    
        // condition die bei neuem Eintrag der DatenZuModulListe auftritt
        boost::condition_variable_any DatenZuModulListeEintrag;
    
        // Schranke für bereite Module
        boost::barrier* schranke;  
    
    };
    

    Was muss ich denn beim Vernichten des DatenModuls generell beachten? Kann es sein dass die fehlerhafte Vernichtung mit den Fehlern der beiden Funktionen zu tun hat?
    Was ist eigentlich der Unterschied zwischen Mutex und Lock? Ein Lock ist ein Objekt, das einen Mutex hält (lockt). Also jeder Mutex kann immer nur in einem Lock gefangen sein? Und an welchem mache ich dann ein unlock() und wo ein release() ?


Anmelden zum Antworten