1a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo// Copyright 2015 The Chromium OS Authors. All rights reserved.
2a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo// Use of this source code is governed by a BSD-style license that can be
3a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo// found in the LICENSE file.
4a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
59ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/message_loops/base_message_loop.h>
6a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
7a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo#include <fcntl.h>
8d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <sys/stat.h>
9d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <sys/types.h>
10a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo#include <unistd.h>
11a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
129471399027d4a8e0ef5e1a68429b2e9e93a31e96Elliott Hughes#ifndef __APPLE__
139471399027d4a8e0ef5e1a68429b2e9e93a31e96Elliott Hughes#include <sys/sysmacros.h>
149471399027d4a8e0ef5e1a68429b2e9e93a31e96Elliott Hughes#endif
159471399027d4a8e0ef5e1a68429b2e9e93a31e96Elliott Hughes
1677edc5357e1ff2c507a07d4c97f943910609ee44Alex Deymo#ifndef __ANDROID_HOST__
1777edc5357e1ff2c507a07d4c97f943910609ee44Alex Deymo// Used for MISC_MAJOR. Only required for the target and not always available
1877edc5357e1ff2c507a07d4c97f943910609ee44Alex Deymo// for the host.
1977edc5357e1ff2c507a07d4c97f943910609ee44Alex Deymo#include <linux/major.h>
2077edc5357e1ff2c507a07d4c97f943910609ee44Alex Deymo#endif
2177edc5357e1ff2c507a07d4c97f943910609ee44Alex Deymo
22d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <vector>
23d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
24a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo#include <base/bind.h>
25d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <base/files/file_path.h>
26d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <base/files/file_util.h>
2730ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo#include <base/run_loop.h>
28d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <base/strings/string_number_conversions.h>
29d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <base/strings/string_split.h>
30a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
319ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/location_logging.h>
32d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <brillo/strings/string_utils.h>
33a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
34a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymousing base::Closure;
35a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
36d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymonamespace {
37d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
38d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymoconst char kMiscMinorPath[] = "/proc/misc";
39d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymoconst char kBinderDriverName[] = "binder";
40d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
41d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo}  // namespace
42d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
439ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo {
44a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
45d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymoconst int BaseMessageLoop::kInvalidMinor = -1;
46d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymoconst int BaseMessageLoop::kUninitializedMinor = -2;
47d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
48922d235dca34496fd30e1b15b2bf24b4a6949288Alex DeymoBaseMessageLoop::BaseMessageLoop() {
49ef47c404abf9c2e482c2381d991f45ca23d62beeAlex Deymo  CHECK(!base::MessageLoop::current())
50ef47c404abf9c2e482c2381d991f45ca23d62beeAlex Deymo      << "You can't create a base::MessageLoopForIO when another "
51ef47c404abf9c2e482c2381d991f45ca23d62beeAlex Deymo         "base::MessageLoop is already created for this thread.";
52922d235dca34496fd30e1b15b2bf24b4a6949288Alex Deymo  owned_base_loop_.reset(new base::MessageLoopForIO);
53922d235dca34496fd30e1b15b2bf24b4a6949288Alex Deymo  base_loop_ = owned_base_loop_.get();
54922d235dca34496fd30e1b15b2bf24b4a6949288Alex Deymo}
55922d235dca34496fd30e1b15b2bf24b4a6949288Alex Deymo
56a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoBaseMessageLoop::BaseMessageLoop(base::MessageLoopForIO* base_loop)
57922d235dca34496fd30e1b15b2bf24b4a6949288Alex Deymo    : base_loop_(base_loop) {}
58a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
59a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoBaseMessageLoop::~BaseMessageLoop() {
60a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  for (auto& io_task : io_tasks_) {
61a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    DVLOG_LOC(io_task.second.location(), 1)
62a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo        << "Removing file descriptor watcher task_id " << io_task.first
63a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo        << " leaked on BaseMessageLoop, scheduled from this location.";
6407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    io_task.second.StopWatching();
65a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  }
66a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
67a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // Note all pending canceled delayed tasks when destroying the message loop.
68a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  size_t lazily_deleted_tasks = 0;
69a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  for (const auto& delayed_task : delayed_tasks_) {
70a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    if (delayed_task.second.closure.is_null()) {
71a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      lazily_deleted_tasks++;
72a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    } else {
73a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      DVLOG_LOC(delayed_task.second.location, 1)
74a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo          << "Removing delayed task_id " << delayed_task.first
75a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo          << " leaked on BaseMessageLoop, scheduled from this location.";
76a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    }
77a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  }
78a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (lazily_deleted_tasks) {
79a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    LOG(INFO) << "Leaking " << lazily_deleted_tasks << " canceled tasks.";
80a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  }
81a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
82a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
83a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoMessageLoop::TaskId BaseMessageLoop::PostDelayedTask(
84a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    const tracked_objects::Location& from_here,
85a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    const Closure &task,
86a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    base::TimeDelta delay) {
87a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  TaskId task_id =  NextTaskId();
88a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  bool base_scheduled = base_loop_->task_runner()->PostDelayedTask(
89a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      from_here,
90a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      base::Bind(&BaseMessageLoop::OnRanPostedTask,
91a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                 weak_ptr_factory_.GetWeakPtr(),
92a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                 task_id),
93a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      delay);
94a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  DVLOG_LOC(from_here, 1) << "Scheduling delayed task_id " << task_id
95a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                          << " to run in " << delay << ".";
96a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (!base_scheduled)
97a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    return MessageLoop::kTaskIdNull;
98a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
99a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  delayed_tasks_.emplace(task_id,
100a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                         DelayedTask{from_here, task_id, std::move(task)});
101a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  return task_id;
102a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
103a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
104a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoMessageLoop::TaskId BaseMessageLoop::WatchFileDescriptor(
105a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    const tracked_objects::Location& from_here,
106a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    int fd,
107a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    WatchMode mode,
108a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    bool persistent,
109a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    const Closure &task) {
110a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // base::MessageLoopForIO CHECKS that "fd >= 0", so we handle that case here.
111a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (fd < 0)
112a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    return MessageLoop::kTaskIdNull;
113a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
114a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  base::MessageLoopForIO::Mode base_mode = base::MessageLoopForIO::WATCH_READ;
115a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  switch (mode) {
116a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    case MessageLoop::kWatchRead:
117a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      base_mode = base::MessageLoopForIO::WATCH_READ;
118a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      break;
119a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    case MessageLoop::kWatchWrite:
120a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      base_mode = base::MessageLoopForIO::WATCH_WRITE;
121a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      break;
122a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    default:
123a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      return MessageLoop::kTaskIdNull;
124a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  }
125a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
126a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  TaskId task_id =  NextTaskId();
127a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  auto it_bool = io_tasks_.emplace(
128a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      std::piecewise_construct,
129a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      std::forward_as_tuple(task_id),
13007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo      std::forward_as_tuple(
13107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo          from_here, this, task_id, fd, base_mode, persistent, task));
132a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // This should always insert a new element.
133a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  DCHECK(it_bool.second);
13407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  bool scheduled = it_bool.first->second.StartWatching();
135a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  DVLOG_LOC(from_here, 1)
136a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      << "Watching fd " << fd << " for "
137a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      << (mode == MessageLoop::kWatchRead ? "reading" : "writing")
138a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      << (persistent ? " persistently" : " just once")
139a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      << " as task_id " << task_id
140a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      << (scheduled ? " successfully" : " failed.");
141a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
142a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (!scheduled) {
143a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    io_tasks_.erase(task_id);
144a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    return MessageLoop::kTaskIdNull;
145a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  }
146d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
14777edc5357e1ff2c507a07d4c97f943910609ee44Alex Deymo#ifndef __ANDROID_HOST__
148d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // Determine if the passed fd is the binder file descriptor. For that, we need
149d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // to check that is a special char device and that the major and minor device
150d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // numbers match. The binder file descriptor can't be removed and added back
151d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // to an epoll group when there's work available to be done by the file
152d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // descriptor due to bugs in the binder driver (b/26524111) when used with
153d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // epoll. Therefore, we flag the binder fd and never attempt to remove it.
154d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // This may cause the binder file descriptor to be attended with higher
155d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // priority and cause starvation of other events.
156d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  struct stat buf;
157d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  if (fstat(fd, &buf) == 0 &&
158d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo      S_ISCHR(buf.st_mode) &&
159d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo      major(buf.st_rdev) == MISC_MAJOR &&
160d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo      minor(buf.st_rdev) == GetBinderMinor()) {
161d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    it_bool.first->second.RunImmediately();
162d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  }
16377edc5357e1ff2c507a07d4c97f943910609ee44Alex Deymo#endif
164d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
165a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  return task_id;
166a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
167a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
168a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymobool BaseMessageLoop::CancelTask(TaskId task_id) {
169a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (task_id == kTaskIdNull)
170a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    return false;
171a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  auto delayed_task_it = delayed_tasks_.find(task_id);
172a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (delayed_task_it == delayed_tasks_.end()) {
173a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    // This might be an IOTask then.
174a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    auto io_task_it = io_tasks_.find(task_id);
175a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    if (io_task_it == io_tasks_.end())
176a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      return false;
17707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    return io_task_it->second.CancelTask();
178a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  }
179a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // A DelayedTask was found for this task_id at this point.
180a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
181a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // Check if the callback was already canceled but we have the entry in
182a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // delayed_tasks_ since it didn't fire yet in the message loop.
183a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (delayed_task_it->second.closure.is_null())
184a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    return false;
185a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
186a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  DVLOG_LOC(delayed_task_it->second.location, 1)
187a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      << "Removing task_id " << task_id << " scheduled from this location.";
188a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // We reset to closure to a null Closure to release all the resources
189a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // used by this closure at this point, but we don't remove the task_id from
190a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // delayed_tasks_ since we can't tell base::MessageLoopForIO to not run it.
191a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  delayed_task_it->second.closure = Closure();
192a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
193a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  return true;
194a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
195a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
196a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymobool BaseMessageLoop::RunOnce(bool may_block) {
197a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  run_once_ = true;
19830ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  base::RunLoop run_loop;  // Uses the base::MessageLoopForIO implicitly.
19930ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  base_run_loop_ = &run_loop;
200a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (!may_block)
20130ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo    run_loop.RunUntilIdle();
202a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  else
20330ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo    run_loop.Run();
20430ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  base_run_loop_ = nullptr;
205a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // If the flag was reset to false, it means a closure was run.
206a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (!run_once_)
207a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    return true;
208a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
209a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  run_once_ = false;
210a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  return false;
211a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
212a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
213a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymovoid BaseMessageLoop::Run() {
21430ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  base::RunLoop run_loop;  // Uses the base::MessageLoopForIO implicitly.
21530ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  base_run_loop_ = &run_loop;
21630ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  run_loop.Run();
21730ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  base_run_loop_ = nullptr;
218a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
219a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
220a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymovoid BaseMessageLoop::BreakLoop() {
22130ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  if (base_run_loop_ == nullptr) {
22230ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo    DVLOG(1) << "Message loop not running, ignoring BreakLoop().";
22330ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo    return;  // Message loop not running, nothing to do.
22430ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  }
22530ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  base_run_loop_->Quit();
22630ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo}
22730ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo
22830ef318cd1d94e896a277324c68b89798e3dbbddAlex DeymoClosure BaseMessageLoop::QuitClosure() const {
22930ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  if (base_run_loop_ == nullptr)
23030ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo    return base::Bind(&base::DoNothing);
23130ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo  return base_run_loop_->QuitClosure();
232a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
233a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
234a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoMessageLoop::TaskId BaseMessageLoop::NextTaskId() {
235a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  TaskId res;
236a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  do {
237a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    res = ++last_id_;
238a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    // We would run out of memory before we run out of task ids.
239a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  } while (!res ||
240a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo           delayed_tasks_.find(res) != delayed_tasks_.end() ||
241a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo           io_tasks_.find(res) != io_tasks_.end());
242a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  return res;
243a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
244a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
245a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymovoid BaseMessageLoop::OnRanPostedTask(MessageLoop::TaskId task_id) {
246a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  auto task_it = delayed_tasks_.find(task_id);
247a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  DCHECK(task_it != delayed_tasks_.end());
248a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (!task_it->second.closure.is_null()) {
249a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    DVLOG_LOC(task_it->second.location, 1)
250a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo        << "Running delayed task_id " << task_id
251a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo        << " scheduled from this location.";
252a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    // Mark the task as canceled while we are running it so CancelTask returns
253a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    // false.
254a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    Closure closure = std::move(task_it->second.closure);
255a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    task_it->second.closure = Closure();
256a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    closure.Run();
257a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
258a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    // If the |run_once_| flag is set, it is because we are instructed to run
259a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    // only once callback.
260a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    if (run_once_) {
261a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo      run_once_ = false;
26230ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo      BreakLoop();
263a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    }
264a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  }
265a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  delayed_tasks_.erase(task_it);
266a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
267a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
26807c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::OnFileReadyPostedTask(MessageLoop::TaskId task_id) {
26907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  auto task_it = io_tasks_.find(task_id);
27007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // Even if this task was canceled while we were waiting in the message loop
27107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // for this method to run, the entry in io_tasks_ should still be present, but
27207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // won't do anything.
27307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  DCHECK(task_it != io_tasks_.end());
27407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  task_it->second.OnFileReadyPostedTask();
27507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo}
27607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo
277d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymoint BaseMessageLoop::ParseBinderMinor(
278d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    const std::string& file_contents) {
279d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  int result = kInvalidMinor;
280d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // Split along '\n', then along the ' '. Note that base::SplitString trims all
281d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // white spaces at the beginning and end after splitting.
282922d235dca34496fd30e1b15b2bf24b4a6949288Alex Deymo  std::vector<std::string> lines =
28380b7ee94e36e2d25a97a262d3b558bbf130c2a01Alex Vakulenko      base::SplitString(file_contents, "\n", base::TRIM_WHITESPACE,
28480b7ee94e36e2d25a97a262d3b558bbf130c2a01Alex Vakulenko                        base::SPLIT_WANT_ALL);
285d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  for (const std::string& line : lines) {
286d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    if (line.empty())
287d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo      continue;
288d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    std::string number;
289d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    std::string name;
290d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    if (!string_utils::SplitAtFirst(line, " ", &number, &name, false))
291d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo      continue;
292d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
293d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    if (name == kBinderDriverName && base::StringToInt(number, &result))
294d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo      break;
295d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  }
296d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  return result;
297d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo}
298d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
299d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymounsigned int BaseMessageLoop::GetBinderMinor() {
300d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  if (binder_minor_ != kUninitializedMinor)
301d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    return binder_minor_;
302d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
303d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  std::string proc_misc;
304d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  if (!base::ReadFileToString(base::FilePath(kMiscMinorPath), &proc_misc))
305d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    return binder_minor_;
306d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  binder_minor_ = ParseBinderMinor(proc_misc);
307d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  return binder_minor_;
308d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo}
309d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
310a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoBaseMessageLoop::IOTask::IOTask(const tracked_objects::Location& location,
311a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                                BaseMessageLoop* loop,
312a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                                MessageLoop::TaskId task_id,
31307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo                                int fd,
31407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo                                base::MessageLoopForIO::Mode base_mode,
315a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                                bool persistent,
316a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                                const Closure& task)
317a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    : location_(location), loop_(loop), task_id_(task_id),
318324b9515118eca1ac9b579af6dd4d9ffc33a023cJay Civelli      fd_(fd), base_mode_(base_mode), persistent_(persistent), closure_(task),
319324b9515118eca1ac9b579af6dd4d9ffc33a023cJay Civelli      fd_watcher_(FROM_HERE) {}
320a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
32107c1779e51680364060f3ec289249869ac7bc5caAlex Deymobool BaseMessageLoop::IOTask::StartWatching() {
32207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  return loop_->base_loop_->WatchFileDescriptor(
32307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo      fd_, persistent_, base_mode_, &fd_watcher_, this);
324a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
325a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
32607c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::IOTask::StopWatching() {
32707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // This is safe to call even if we are not watching for it.
32807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  fd_watcher_.StopWatchingFileDescriptor();
32907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo}
33007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo
33107c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::IOTask::OnFileCanReadWithoutBlocking(int /* fd */) {
33207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  OnFileReady();
33307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo}
33407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo
33507c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::IOTask::OnFileCanWriteWithoutBlocking(int /* fd */) {
33607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  OnFileReady();
33707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo}
33807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo
33907c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::IOTask::OnFileReady() {
340d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // For file descriptors marked with the immediate_run flag, we don't call
341d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // StopWatching() and wait, instead we dispatch the callback immediately.
342d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  if (immediate_run_) {
343d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    posted_task_pending_ = true;
344d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    OnFileReadyPostedTask();
345d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    return;
346d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  }
347d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo
34807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // When the file descriptor becomes available we stop watching for it and
34907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // schedule a task to run the callback from the main loop. The callback will
350d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo  // run using the same scheduler used to run other delayed tasks, avoiding
35107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // starvation of the available posted tasks if there are file descriptors
35207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // always available. The new posted task will use the same TaskId as the
35307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // current file descriptor watching task an could be canceled in either state,
35407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // when waiting for the file descriptor or waiting in the main loop.
35507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  StopWatching();
35607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  bool base_scheduled = loop_->base_loop_->task_runner()->PostTask(
35707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo      location_,
35807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo      base::Bind(&BaseMessageLoop::OnFileReadyPostedTask,
35907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo                 loop_->weak_ptr_factory_.GetWeakPtr(),
36007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo                 task_id_));
36107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  posted_task_pending_ = true;
36207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  if (base_scheduled) {
36307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    DVLOG_LOC(location_, 1)
36407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo        << "Dispatching task_id " << task_id_ << " for "
36507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo        << (base_mode_ == base::MessageLoopForIO::WATCH_READ ?
36607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo            "reading" : "writing")
36707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo        << " file descriptor " << fd_ << ", scheduled from this location.";
36807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  } else {
36907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    // In the rare case that PostTask() fails, we fall back to run it directly.
37007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    // This would indicate a bigger problem with the message loop setup.
37107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    LOG(ERROR) << "Error on base::MessageLoopForIO::PostTask().";
37207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    OnFileReadyPostedTask();
37307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  }
374a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
375a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
37607c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::IOTask::OnFileReadyPostedTask() {
377a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // We can't access |this| after running the |closure_| since it could call
378a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  // CancelTask on its own task_id, so we copy the members we need now.
379a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  BaseMessageLoop* loop_ptr = loop_;
38007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  DCHECK(posted_task_pending_ = true);
38107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  posted_task_pending_ = false;
38207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo
38307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // If this task was already canceled, the closure will be null and there is
38407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // nothing else to do here. This execution doesn't count a step for RunOnce()
38507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // unless we have a callback to run.
38607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  if (closure_.is_null()) {
38707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    loop_->io_tasks_.erase(task_id_);
38807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    return;
38907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  }
390a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
391a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  DVLOG_LOC(location_, 1)
39207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo      << "Running task_id " << task_id_ << " for "
39307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo      << (base_mode_ == base::MessageLoopForIO::WATCH_READ ?
39407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo          "reading" : "writing")
39507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo      << " file descriptor " << fd_ << ", scheduled from this location.";
396a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
397a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (persistent_) {
398a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    // In the persistent case we just run the callback. If this callback cancels
39907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    // the task id, we can't access |this| anymore, so we re-start watching the
400d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    // file descriptor before running the callback, unless this is a fd where
401d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    // we didn't stop watching the file descriptor when it became available.
402d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo    if (!immediate_run_)
403d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo      StartWatching();
404a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    closure_.Run();
405a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  } else {
406a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    // This will destroy |this|, the fd_watcher and therefore stop watching this
407a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    // file descriptor.
408a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    Closure closure_copy = std::move(closure_);
409a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    loop_->io_tasks_.erase(task_id_);
410a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    // Run the closure from the local copy we just made.
411a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    closure_copy.Run();
412a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  }
413a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
414a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  if (loop_ptr->run_once_) {
415a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo    loop_ptr->run_once_ = false;
41630ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo    loop_ptr->BreakLoop();
417a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  }
418a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo}
419a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo
42007c1779e51680364060f3ec289249869ac7bc5caAlex Deymobool BaseMessageLoop::IOTask::CancelTask() {
42107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  if (closure_.is_null())
42207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    return false;
42307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo
42407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  DVLOG_LOC(location_, 1)
42507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo      << "Removing task_id " << task_id_ << " scheduled from this location.";
42607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo
42707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  if (!posted_task_pending_) {
42807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    // Destroying the FileDescriptorWatcher implicitly stops watching the file
42907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    // descriptor. This will delete our instance.
43007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    loop_->io_tasks_.erase(task_id_);
43107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo    return true;
43207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  }
43307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // The IOTask is waiting for the message loop to run its delayed task, so
43407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // it is not watching for the file descriptor. We release the closure
43507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // resources now but keep the IOTask instance alive while we wait for the
43607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  // callback to run and delete the IOTask.
43707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  closure_ = Closure();
43807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo  return true;
43907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo}
44007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo
4419ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko}  // namespace brillo
442