summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2010-04-08 18:42:48 -0400
committerMathias Stearn <mathias@10gen.com>2010-04-08 19:57:48 -0400
commitdfa0c41aa11ae1d97576e1b72180f0a398d4894a (patch)
tree0179031da66f860c4459d785e7f82fc4c21847d5
parentc4769e9f86b2cd256aca1276ece362f3795a1ee8 (diff)
downloadmongo-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.cpp8
-rw-r--r--util/mmap.h9
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?)