Don't do work inside assert(). Ever.
The Mac crash key manipulation code was intended to be thread-safe through the provision of a mutex. The mutex operations were done inside an assert(). assert() is a no-op in NDEBUG (release) builds. Therefore, in release builds, these operations were occurring without being protected by any mutex at all, and were nowhere near thread-safe. BUG=chromium:331268 R=rsesek@chromium.org Review URL: https://breakpad.appspot.com/1034002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1270 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
1e99113fbe
commit
3ea04ec479
2 changed files with 26 additions and 32 deletions
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#import "client/ios/Breakpad.h"
|
#import "client/ios/Breakpad.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -92,35 +93,31 @@ pthread_mutex_t gDictionaryMutex;
|
||||||
// Its destructor will first re-protect the memory then release the lock.
|
// Its destructor will first re-protect the memory then release the lock.
|
||||||
class ProtectedMemoryLocker {
|
class ProtectedMemoryLocker {
|
||||||
public:
|
public:
|
||||||
// allocator may be NULL, in which case no Protect() or Unprotect() calls
|
|
||||||
// will be made, but a lock will still be taken
|
|
||||||
ProtectedMemoryLocker(pthread_mutex_t *mutex,
|
ProtectedMemoryLocker(pthread_mutex_t *mutex,
|
||||||
ProtectedMemoryAllocator *allocator)
|
ProtectedMemoryAllocator *allocator)
|
||||||
: mutex_(mutex), allocator_(allocator) {
|
: mutex_(mutex),
|
||||||
|
allocator_(allocator) {
|
||||||
// Lock the mutex
|
// Lock the mutex
|
||||||
assert(pthread_mutex_lock(mutex_) == 0);
|
int rv = pthread_mutex_lock(mutex_);
|
||||||
|
assert(rv == 0);
|
||||||
|
|
||||||
// Unprotect the memory
|
// Unprotect the memory
|
||||||
if (allocator_ ) {
|
|
||||||
allocator_->Unprotect();
|
allocator_->Unprotect();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
~ProtectedMemoryLocker() {
|
~ProtectedMemoryLocker() {
|
||||||
// First protect the memory
|
// First protect the memory
|
||||||
if (allocator_) {
|
|
||||||
allocator_->Protect();
|
allocator_->Protect();
|
||||||
}
|
|
||||||
|
|
||||||
// Then unlock the mutex
|
// Then unlock the mutex
|
||||||
assert(pthread_mutex_unlock(mutex_) == 0);
|
int rv = pthread_mutex_unlock(mutex_);
|
||||||
|
assert(rv == 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Keep anybody from ever creating one of these things not on the stack.
|
ProtectedMemoryLocker();
|
||||||
ProtectedMemoryLocker() { }
|
|
||||||
ProtectedMemoryLocker(const ProtectedMemoryLocker&);
|
ProtectedMemoryLocker(const ProtectedMemoryLocker&);
|
||||||
ProtectedMemoryLocker & operator=(ProtectedMemoryLocker&);
|
ProtectedMemoryLocker& operator=(const ProtectedMemoryLocker&);
|
||||||
|
|
||||||
pthread_mutex_t *mutex_;
|
pthread_mutex_t *mutex_;
|
||||||
ProtectedMemoryAllocator *allocator_;
|
ProtectedMemoryAllocator *allocator_;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#import "client/mac/Framework/Breakpad.h"
|
#import "client/mac/Framework/Breakpad.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -96,35 +97,31 @@ pthread_mutex_t gDictionaryMutex;
|
||||||
// Its destructor will first re-protect the memory then release the lock.
|
// Its destructor will first re-protect the memory then release the lock.
|
||||||
class ProtectedMemoryLocker {
|
class ProtectedMemoryLocker {
|
||||||
public:
|
public:
|
||||||
// allocator may be NULL, in which case no Protect() or Unprotect() calls
|
|
||||||
// will be made, but a lock will still be taken
|
|
||||||
ProtectedMemoryLocker(pthread_mutex_t *mutex,
|
ProtectedMemoryLocker(pthread_mutex_t *mutex,
|
||||||
ProtectedMemoryAllocator *allocator)
|
ProtectedMemoryAllocator *allocator)
|
||||||
: mutex_(mutex), allocator_(allocator) {
|
: mutex_(mutex),
|
||||||
|
allocator_(allocator) {
|
||||||
// Lock the mutex
|
// Lock the mutex
|
||||||
assert(pthread_mutex_lock(mutex_) == 0);
|
int rv = pthread_mutex_lock(mutex_);
|
||||||
|
assert(rv == 0);
|
||||||
|
|
||||||
// Unprotect the memory
|
// Unprotect the memory
|
||||||
if (allocator_ ) {
|
|
||||||
allocator_->Unprotect();
|
allocator_->Unprotect();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
~ProtectedMemoryLocker() {
|
~ProtectedMemoryLocker() {
|
||||||
// First protect the memory
|
// First protect the memory
|
||||||
if (allocator_) {
|
|
||||||
allocator_->Protect();
|
allocator_->Protect();
|
||||||
}
|
|
||||||
|
|
||||||
// Then unlock the mutex
|
// Then unlock the mutex
|
||||||
assert(pthread_mutex_unlock(mutex_) == 0);
|
int rv = pthread_mutex_unlock(mutex_);
|
||||||
|
assert(rv == 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Keep anybody from ever creating one of these things not on the stack.
|
ProtectedMemoryLocker();
|
||||||
ProtectedMemoryLocker() { }
|
|
||||||
ProtectedMemoryLocker(const ProtectedMemoryLocker&);
|
ProtectedMemoryLocker(const ProtectedMemoryLocker&);
|
||||||
ProtectedMemoryLocker & operator=(ProtectedMemoryLocker&);
|
ProtectedMemoryLocker& operator=(const ProtectedMemoryLocker&);
|
||||||
|
|
||||||
pthread_mutex_t *mutex_;
|
pthread_mutex_t *mutex_;
|
||||||
ProtectedMemoryAllocator *allocator_;
|
ProtectedMemoryAllocator *allocator_;
|
||||||
|
|
Loading…
Reference in a new issue