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

Side by Side Diff: base/message_pump_win.cc

Issue 10392163: Handle rare conditions, like message queue exhaustion (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 7 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/message_pump_win.h" 5 #include "base/message_pump_win.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/win/wrapped_window_proc.h" 11 #include "base/win/wrapped_window_proc.h"
12 12
13 namespace {
14
15 enum MessageLoopProblems {
16 MESSAGE_POST_ERROR,
17 COMPLETION_POST_ERROR,
18 SET_TIMER_ERROR,
19 MESSAGE_LOOP_PROBLEM_MAX,
20 };
21
22 } // namespace
23
13 namespace base { 24 namespace base {
14 25
15 static const wchar_t kWndClass[] = L"Chrome_MessagePumpWindow"; 26 static const wchar_t kWndClass[] = L"Chrome_MessagePumpWindow";
16 27
17 // Message sent to get an additional time slice for pumping (processing) another 28 // Message sent to get an additional time slice for pumping (processing) another
18 // task (a series of such messages creates a continuous task pump). 29 // task (a series of such messages creates a continuous task pump).
19 static const int kMsgHaveWork = WM_USER + 1; 30 static const int kMsgHaveWork = WM_USER + 1;
20 31
21 //----------------------------------------------------------------------------- 32 //-----------------------------------------------------------------------------
22 // MessagePumpWin public: 33 // MessagePumpWin public:
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 MessagePumpForUI::~MessagePumpForUI() { 100 MessagePumpForUI::~MessagePumpForUI() {
90 DestroyWindow(message_hwnd_); 101 DestroyWindow(message_hwnd_);
91 UnregisterClass(kWndClass, GetModuleHandle(NULL)); 102 UnregisterClass(kWndClass, GetModuleHandle(NULL));
92 } 103 }
93 104
94 void MessagePumpForUI::ScheduleWork() { 105 void MessagePumpForUI::ScheduleWork() {
95 if (InterlockedExchange(&have_work_, 1)) 106 if (InterlockedExchange(&have_work_, 1))
96 return; // Someone else continued the pumping. 107 return; // Someone else continued the pumping.
97 108
98 // Make sure the MessagePump does some work for us. 109 // Make sure the MessagePump does some work for us.
99 PostMessage(message_hwnd_, kMsgHaveWork, reinterpret_cast<WPARAM>(this), 0); 110 BOOL ret = PostMessage(message_hwnd_, kMsgHaveWork,
111 reinterpret_cast<WPARAM>(this), 0);
112 if (ret)
113 return; // There was room in the Window Message queue.
114
115 // We have failed to insert a have-work message, so there is a chance that we
116 // will starve tasks/timers while sitting in a nested message loop. Nested
117 // loops only look at Windows Message queues, and don't look at *our* task
118 // queues, etc., so we might not get a time slice in such. :-(
119 // We could abort here, but the fear is that this failure mode is plausibly
120 // common (queue is full, of about 2000 messages), so we'll do a near-graceful
121 // recovery. Nested loops are pretty transient (we think), so this will
122 // probably be recoverable.
123 InterlockedExchange(&have_work_, 0); // Clarify that we didn't really insert.
124 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", MESSAGE_POST_ERROR,
125 MESSAGE_LOOP_PROBLEM_MAX);
100 } 126 }
101 127
102 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 128 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
103 // 129 //
104 // We would *like* to provide high resolution timers. Windows timers using 130 // We would *like* to provide high resolution timers. Windows timers using
105 // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup 131 // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup
106 // mechanism because the application can enter modal windows loops where it 132 // mechanism because the application can enter modal windows loops where it
107 // is not running our MessageLoop; the only way to have our timers fire in 133 // is not running our MessageLoop; the only way to have our timers fire in
108 // these cases is to post messages there. 134 // these cases is to post messages there.
109 // 135 //
(...skipping 12 matching lines...) Expand all
122 // 148 //
123 delayed_work_time_ = delayed_work_time; 149 delayed_work_time_ = delayed_work_time;
124 150
125 int delay_msec = GetCurrentDelay(); 151 int delay_msec = GetCurrentDelay();
126 DCHECK_GE(delay_msec, 0); 152 DCHECK_GE(delay_msec, 0);
127 if (delay_msec < USER_TIMER_MINIMUM) 153 if (delay_msec < USER_TIMER_MINIMUM)
128 delay_msec = USER_TIMER_MINIMUM; 154 delay_msec = USER_TIMER_MINIMUM;
129 155
130 // Create a WM_TIMER event that will wake us up to check for any pending 156 // Create a WM_TIMER event that will wake us up to check for any pending
131 // timers (in case we are running within a nested, external sub-pump). 157 // timers (in case we are running within a nested, external sub-pump).
132 SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), delay_msec, NULL); 158 BOOL ret = SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this),
159 delay_msec, NULL);
160 if (ret)
161 return;
162 // If we can't set timers, we are in big trouble... but cross our fingers for
163 // now.
164 // TODO(jar): If we don't see this error, use a CHECK() here instead.
165 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR,
166 MESSAGE_LOOP_PROBLEM_MAX);
133 } 167 }
134 168
135 void MessagePumpForUI::PumpOutPendingPaintMessages() { 169 void MessagePumpForUI::PumpOutPendingPaintMessages() {
136 // If we are being called outside of the context of Run, then don't try to do 170 // If we are being called outside of the context of Run, then don't try to do
137 // any work. 171 // any work.
138 if (!state_) 172 if (!state_)
139 return; 173 return;
140 174
141 // Create a mini-message-pump to force immediate processing of only Windows 175 // Create a mini-message-pump to force immediate processing of only Windows
142 // WM_PAINT messages. Don't provide an infinite loop, but do enough peeking 176 // WM_PAINT messages. Don't provide an infinite loop, but do enough peeking
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 } 447 }
414 448
415 void MessagePumpForIO::ScheduleWork() { 449 void MessagePumpForIO::ScheduleWork() {
416 if (InterlockedExchange(&have_work_, 1)) 450 if (InterlockedExchange(&have_work_, 1))
417 return; // Someone else continued the pumping. 451 return; // Someone else continued the pumping.
418 452
419 // Make sure the MessagePump does some work for us. 453 // Make sure the MessagePump does some work for us.
420 BOOL ret = PostQueuedCompletionStatus(port_, 0, 454 BOOL ret = PostQueuedCompletionStatus(port_, 0,
421 reinterpret_cast<ULONG_PTR>(this), 455 reinterpret_cast<ULONG_PTR>(this),
422 reinterpret_cast<OVERLAPPED*>(this)); 456 reinterpret_cast<OVERLAPPED*>(this));
423 DCHECK(ret); 457 if (ret)
458 return; // Post worked perfectly.
459
460 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery.
461 InterlockedExchange(&have_work_, 0); // Clarify that we didn't succeed.
462 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR,
463 MESSAGE_LOOP_PROBLEM_MAX);
424 } 464 }
425 465
426 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 466 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
427 // We know that we can't be blocked right now since this method can only be 467 // We know that we can't be blocked right now since this method can only be
428 // called on the same thread as Run, so we only need to update our record of 468 // called on the same thread as Run, so we only need to update our record of
429 // how long to sleep when we do sleep. 469 // how long to sleep when we do sleep.
430 delayed_work_time_ = delayed_work_time; 470 delayed_work_time_ = delayed_work_time;
431 } 471 }
432 472
433 void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle, 473 void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle,
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 614
575 void MessagePumpForIO::WillProcessIOEvent() { 615 void MessagePumpForIO::WillProcessIOEvent() {
576 FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent()); 616 FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent());
577 } 617 }
578 618
579 void MessagePumpForIO::DidProcessIOEvent() { 619 void MessagePumpForIO::DidProcessIOEvent() {
580 FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent()); 620 FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent());
581 } 621 }
582 622
583 } // namespace base 623 } // namespace base
OLDNEW
« 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