diff options
author | Mathias Stearn <mathias@10gen.com> | 2010-04-08 18:42:48 -0400 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2010-04-08 19:57:48 -0400 |
commit | dfa0c41aa11ae1d97576e1b72180f0a398d4894a (patch) | |
tree | 0179031da66f860c4459d785e7f82fc4c21847d5 | |
parent | c4769e9f86b2cd256aca1276ece362f3795a1ee8 (diff) | |
download | mongo-dfa0c41aa11ae1d97576e1b72180f0a398d4894a.tar.gz |
Prevent calls to pure virtual functions in MongoFile SERVER-988
The issue was that during construction and destruction an object's vtable
points to the current type rather than the most derived type. ~MongoFile() tried
to take a lock, but the function holding the lock tried to use the object,
calling either the close() or flush() virtual methods. The solution was to move
the call that needed the lock to the most derived class's destructor. The
easiest way to increase the probability of this crash is by using --syncdelay 1.
-rw-r--r-- | util/mmap.cpp | 8 | ||||
-rw-r--r-- | util/mmap.h | 9 |
2 files changed, 11 insertions, 6 deletions
diff --git a/util/mmap.cpp b/util/mmap.cpp index c200ce9dcd3..ea966331761 100644 --- a/util/mmap.cpp +++ b/util/mmap.cpp @@ -57,7 +57,7 @@ namespace mongo { static set<MongoFile*> mmfiles; static mongo::mutex mmmutex; - MongoFile::~MongoFile() { + void MongoFile::destroyed() { scoped_lock lk( mmmutex ); mmfiles.erase(this); } @@ -70,6 +70,9 @@ namespace mongo { return; } ++closingAllFiles; + + scoped_lock lk( mmmutex ); + ProgressMeter pm( mmfiles.size() , 2 , 1 ); for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ){ (*i)->close(); @@ -99,9 +102,6 @@ namespace mongo { if ( ! mmf ) continue; - PRINT(mmf); - PRINT(typeid(mmf).name()); - mmf->flush( sync ); } return num; diff --git a/util/mmap.h b/util/mmap.h index 1cde87f5039..5cc5588040b 100644 --- a/util/mmap.h +++ b/util/mmap.h @@ -24,7 +24,9 @@ namespace mongo { protected: virtual void close() = 0; virtual void flush(bool sync) = 0; + void created(); /* subclass must call after create */ + void destroyed(); /* subclass must call in destructor */ public: virtual long length() = 0; @@ -32,7 +34,7 @@ namespace mongo { SEQUENTIAL = 1 // hint - e.g. FILE_FLAG_SEQUENTIAL_SCAN on windows }; - virtual ~MongoFile(); + virtual ~MongoFile() {} static int flushAll( bool sync ); // returns n flushed static long long totalMappedLength(); @@ -75,7 +77,10 @@ namespace mongo { }; MemoryMappedFile(); - ~MemoryMappedFile() { close(); } + ~MemoryMappedFile() { + destroyed(); + close(); + } void close(); // Throws exception if file doesn't exist. (dm may2010: not sure if this is always true?) |