Bug 1240985 - IPC glib deadlock fix (r=jld)

This commit is contained in:
Bill McCloskey 2016-01-19 17:19:22 -08:00
parent a6331d995f
commit cdd0283429
2 changed files with 15 additions and 4 deletions

View File

@ -124,7 +124,8 @@ namespace base {
MessagePumpForUI::MessagePumpForUI()
: state_(NULL),
context_(g_main_context_default()),
wakeup_gpollfd_(new GPollFD) {
wakeup_gpollfd_(new GPollFD),
pipe_full_(false) {
// Create our wakeup pipe, which is used to flag when work was scheduled.
int fds[2];
CHECK(pipe(fds) == 0);
@ -230,10 +231,12 @@ bool MessagePumpForUI::HandleCheck() {
if (!state_) // state_ may be null during tests.
return false;
// 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.
// We should only ever have a single message on the wakeup pipe since we only
// write to the pipe when pipe_full_ is false. The glib poll will tell us
// whether there was data, so this read shouldn't block.
if (wakeup_gpollfd_->revents & G_IO_IN) {
pipe_full_ = false;
char msg;
if (HANDLE_EINTR(read(wakeup_pipe_read_, &msg, 1)) != 1 || msg != '!') {
NOTREACHED() << "Error reading from the wakeup pipe.";
@ -297,6 +300,11 @@ void MessagePumpForUI::Quit() {
}
void MessagePumpForUI::ScheduleWork() {
bool was_full = pipe_full_.exchange(true);
if (was_full) {
return;
}
// 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.

View File

@ -9,6 +9,7 @@
#include "base/observer_list.h"
#include "base/time.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Atomics.h"
typedef union _GdkEvent GdkEvent;
typedef struct _GMainContext GMainContext;
@ -131,6 +132,8 @@ class MessagePumpForUI : public MessagePump {
// Use an autoptr to avoid needing the definition of GPollFD in the header.
mozilla::UniquePtr<GPollFD> wakeup_gpollfd_;
mozilla::Atomic<bool> pipe_full_;
// List of observers.
ObserverList<Observer> observers_;