summaryrefslogtreecommitdiffstats
path: root/base/message_pump_glib.cc
diff options
context:
space:
mode:
authordeanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-18 01:30:42 +0000
committerdeanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-18 01:30:42 +0000
commitaa0f26699ba66418e3d8fd06ba086142d7012377 (patch)
treed0f750093383b3fce661457968dfd05d6116f698 /base/message_pump_glib.cc
parent7e503425499371c6eb68946bbd4bf63e652aff3d (diff)
downloadchromium_src-aa0f26699ba66418e3d8fd06ba086142d7012377.zip
chromium_src-aa0f26699ba66418e3d8fd06ba086142d7012377.tar.gz
chromium_src-aa0f26699ba66418e3d8fd06ba086142d7012377.tar.bz2
Fix the glib pump getting wedged.
I had previously used g_main_context_wakeup which uses glib's internal wakeup pipe. However, this won't ensure that our Dispatch method is called, so I think the poll() was returning, but our events never realized this so we kept on blocking infinitely. We need to make sure our Dispatch() is run when there is a wakeup, which means we have to use our own wakeup pipe so we can handle the event. Review URL: http://codereview.chromium.org/11432 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5590 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/message_pump_glib.cc')
-rw-r--r--base/message_pump_glib.cc26
1 files changed, 25 insertions, 1 deletions
diff --git a/base/message_pump_glib.cc b/base/message_pump_glib.cc
index 3201f29..2ff3cc0 100644
--- a/base/message_pump_glib.cc
+++ b/base/message_pump_glib.cc
@@ -93,8 +93,17 @@ namespace base {
MessagePumpForUI::MessagePumpForUI()
: state_(NULL),
context_(g_main_context_default()) {
+ // Create our wakeup pipe, which is used to flag when work was scheduled.
+ int fds[2];
+ CHECK(pipe(fds) == 0);
+ wakeup_pipe_read_ = fds[0];
+ wakeup_pipe_write_ = fds[1];
+ wakeup_gpollfd_.fd = wakeup_pipe_read_;
+ wakeup_gpollfd_.events = G_IO_IN;
+
work_source_ = g_source_new(&WorkSourceFuncs, sizeof(WorkSource));
static_cast<WorkSource*>(work_source_)->pump = this;
+ g_source_add_poll(work_source_, &wakeup_gpollfd_);
// Use a low priority so that we let other events in the queue go first.
g_source_set_priority(work_source_, G_PRIORITY_DEFAULT_IDLE);
// This is needed to allow Run calls inside Dispatch.
@@ -105,6 +114,8 @@ MessagePumpForUI::MessagePumpForUI()
MessagePumpForUI::~MessagePumpForUI() {
g_source_destroy(work_source_);
g_source_unref(work_source_);
+ close(wakeup_pipe_read_);
+ close(wakeup_pipe_write_);
}
void MessagePumpForUI::Run(Delegate* delegate) {
@@ -161,6 +172,16 @@ int MessagePumpForUI::HandlePrepare() {
}
void MessagePumpForUI::HandleDispatch() {
+ // We should only ever have a single message on the wakeup pipe, since we
+ // are only signaled when the queue went from empty to non-empty. The glib
+ // poll will tell us whether there was data, so this read shouldn't block.
+ if (wakeup_gpollfd_.revents & G_IO_IN) {
+ char msg;
+ if (read(wakeup_pipe_read_, &msg, 1) != 1 || msg != '!') {
+ NOTREACHED() << "Error reading from the wakeup pipe.";
+ }
+ }
+
if (state_->should_quit)
return;
@@ -200,7 +221,10 @@ void MessagePumpForUI::ScheduleWork() {
// This can be called on any thread, so we don't want to touch any state
// variables as we would then need locks all over. This ensures that if
// we are sleeping in a poll that we will wake up.
- g_main_context_wakeup(context_);
+ char msg = '!';
+ if (write(wakeup_pipe_write_, &msg, 1) != 1) {
+ NOTREACHED() << "Could not write to the UI message loop wakeup pipe!";
+ }
}
void MessagePumpForUI::ScheduleDelayedWork(const Time& delayed_work_time) {