diff options
author | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-18 01:30:42 +0000 |
---|---|---|
committer | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-18 01:30:42 +0000 |
commit | aa0f26699ba66418e3d8fd06ba086142d7012377 (patch) | |
tree | d0f750093383b3fce661457968dfd05d6116f698 /base/message_pump_glib.cc | |
parent | 7e503425499371c6eb68946bbd4bf63e652aff3d (diff) | |
download | chromium_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.cc | 26 |
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) { |