Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(977)

Unified Diff: base/waitable_event_posix.cc

Issue 173059: Ensure that SyncWaiter condition variables cannot be destroyed during a broadcast (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/waitable_event_posix.cc
===================================================================
--- base/waitable_event_posix.cc (revision 23711)
+++ base/waitable_event_posix.cc (working copy)
@@ -76,36 +76,37 @@
// Synchronous waits
// -----------------------------------------------------------------------------
-// This is an synchronous waiter. The thread is waiting on the given condition
+// This is a synchronous waiter. The thread is waiting on the given condition
// variable and the fired flag in this object.
// -----------------------------------------------------------------------------
class SyncWaiter : public WaitableEvent::Waiter {
public:
- SyncWaiter(ConditionVariable* cv, Lock* lock)
+ SyncWaiter()
: fired_(false),
- cv_(cv),
- lock_(lock),
- signaling_event_(NULL) {
+ signaling_event_(NULL),
+ lock_(),
agl 2009/08/19 17:35:35 Isn't this line a no-op?
+ cv_(&lock_) {
}
- bool Fire(WaitableEvent *signaling_event) {
- lock_->Acquire();
- const bool previous_value = fired_;
- fired_ = true;
- if (!previous_value)
- signaling_event_ = signaling_event;
- lock_->Release();
+ bool Fire(WaitableEvent* signaling_event) {
+ AutoLock locked(lock_);
- if (previous_value)
+ if (fired_)
return false;
- cv_->Broadcast();
+ fired_ = true;
+ signaling_event_ = signaling_event;
- // SyncWaiters are stack allocated on the stack of the blocking thread.
+ cv_.Broadcast();
+
+ // Unlike AsyncWaiter objects, SyncWaiter objects are stack-allocated on
+ // the blocking thread's stack. There is no |delete this;| in Fire. The
+ // SyncWaiter object is destroyed when it goes out of scope.
+
return true;
}
- WaitableEvent* signaled_event() const {
+ WaitableEvent* signaling_event() const {
return signaling_event_;
}
@@ -133,11 +134,19 @@
fired_ = true;
}
+ Lock* lock() {
+ return &lock_;
+ }
+
+ ConditionVariable* cv() {
+ return &cv_;
+ }
+
private:
bool fired_;
- ConditionVariable *const cv_;
- Lock *const lock_;
WaitableEvent* signaling_event_; // The WaitableEvent which woke us
+ Lock lock_;
+ ConditionVariable cv_;
};
bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
@@ -156,10 +165,8 @@
return true;
}
- Lock lock;
- lock.Acquire();
- ConditionVariable cv(&lock);
- SyncWaiter sw(&cv, &lock);
+ SyncWaiter sw;
+ sw.lock()->Acquire();
Enqueue(&sw);
kernel_->lock_.Release();
@@ -173,13 +180,13 @@
if (sw.fired() || (finite_time && current_time >= end_time)) {
const bool return_value = sw.fired();
- // We can't acquire @lock_ before releasing @lock (because of locking
- // order), however, inbetween the two a signal could be fired and @sw
- // would accept it, however we will still return false, so the signal
- // would be lost on an auto-reset WaitableEvent. Thus we call Disable
- // which makes sw::Fire return false.
+ // We can't acquire @lock_ before releasing the SyncWaiter lock (because
+ // of locking order), however, in between the two a signal could be fired
+ // and @sw would accept it, however we will still return false, so the
+ // signal would be lost on an auto-reset WaitableEvent. Thus we call
+ // Disable which makes sw::Fire return false.
sw.Disable();
- lock.Release();
+ sw.lock()->Release();
kernel_->lock_.Acquire();
kernel_->Dequeue(&sw, &sw);
@@ -190,9 +197,9 @@
if (finite_time) {
const TimeDelta max_wait(end_time - current_time);
- cv.TimedWait(max_wait);
+ sw.cv()->TimedWait(max_wait);
} else {
- cv.Wait();
+ sw.cv()->Wait();
}
}
}
@@ -237,9 +244,7 @@
DCHECK(waitables[i].first != waitables[i+1].first);
}
- Lock lock;
- ConditionVariable cv(&lock);
- SyncWaiter sw(&cv, &lock);
+ SyncWaiter sw;
const size_t r = EnqueueMany(&waitables[0], count, &sw);
if (r) {
@@ -252,7 +257,7 @@
// At this point, we hold the locks on all the WaitableEvents and we have
// enqueued our waiter in them all.
- lock.Acquire();
+ sw.lock()->Acquire();
// Release the WaitableEvent locks in the reverse order
for (size_t i = 0; i < count; ++i) {
waitables[count - (1 + i)].first->kernel_->lock_.Release();
@@ -262,12 +267,12 @@
if (sw.fired())
break;
- cv.Wait();
+ sw.cv()->Wait();
}
- lock.Release();
+ sw.lock()->Release();
// The address of the WaitableEvent which fired is stored in the SyncWaiter.
- WaitableEvent *const signaled_event = sw.signaled_event();
+ WaitableEvent *const signaled_event = sw.signaling_event();
// This will store the index of the raw_waitables which fired.
size_t signaled_index = 0;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698