base_message_loop.cc revision d671746a66d87edf9598cfbe077b3430e50a09d3
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 <linux/major.h> 9d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <sys/stat.h> 10d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <sys/types.h> 11a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo#include <unistd.h> 12a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 13d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <vector> 14d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 15a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo#include <base/bind.h> 16d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <base/files/file_path.h> 17d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <base/files/file_util.h> 1830ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo#include <base/run_loop.h> 19d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <base/strings/string_number_conversions.h> 20d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <base/strings/string_split.h> 21a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 229ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/location_logging.h> 23d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo#include <brillo/strings/string_utils.h> 24a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 25a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymousing base::Closure; 26a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 27d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymonamespace { 28d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 29d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymoconst char kMiscMinorPath[] = "/proc/misc"; 30d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymoconst char kBinderDriverName[] = "binder"; 31d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 32d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo} // namespace 33d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 349ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo { 35a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 36d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymoconst int BaseMessageLoop::kInvalidMinor = -1; 37d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymoconst int BaseMessageLoop::kUninitializedMinor = -2; 38d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 39a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoBaseMessageLoop::BaseMessageLoop(base::MessageLoopForIO* base_loop) 40a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo : base_loop_(base_loop), 41a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo weak_ptr_factory_(this) {} 42a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 43a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoBaseMessageLoop::~BaseMessageLoop() { 44a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo for (auto& io_task : io_tasks_) { 45a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo DVLOG_LOC(io_task.second.location(), 1) 46a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << "Removing file descriptor watcher task_id " << io_task.first 47a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << " leaked on BaseMessageLoop, scheduled from this location."; 4807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo io_task.second.StopWatching(); 49a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 50a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 51a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // Note all pending canceled delayed tasks when destroying the message loop. 52a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo size_t lazily_deleted_tasks = 0; 53a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo for (const auto& delayed_task : delayed_tasks_) { 54a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (delayed_task.second.closure.is_null()) { 55a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo lazily_deleted_tasks++; 56a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } else { 57a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo DVLOG_LOC(delayed_task.second.location, 1) 58a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << "Removing delayed task_id " << delayed_task.first 59a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << " leaked on BaseMessageLoop, scheduled from this location."; 60a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 61a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 62a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (lazily_deleted_tasks) { 63a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo LOG(INFO) << "Leaking " << lazily_deleted_tasks << " canceled tasks."; 64a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 65a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 66a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 67a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoMessageLoop::TaskId BaseMessageLoop::PostDelayedTask( 68a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo const tracked_objects::Location& from_here, 69a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo const Closure &task, 70a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo base::TimeDelta delay) { 71a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo TaskId task_id = NextTaskId(); 72a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo bool base_scheduled = base_loop_->task_runner()->PostDelayedTask( 73a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo from_here, 74a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo base::Bind(&BaseMessageLoop::OnRanPostedTask, 75a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo weak_ptr_factory_.GetWeakPtr(), 76a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo task_id), 77a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo delay); 78a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo DVLOG_LOC(from_here, 1) << "Scheduling delayed task_id " << task_id 79a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << " to run in " << delay << "."; 80a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (!base_scheduled) 81a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return MessageLoop::kTaskIdNull; 82a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 83a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo delayed_tasks_.emplace(task_id, 84a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo DelayedTask{from_here, task_id, std::move(task)}); 85a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return task_id; 86a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 87a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 88a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoMessageLoop::TaskId BaseMessageLoop::WatchFileDescriptor( 89a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo const tracked_objects::Location& from_here, 90a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo int fd, 91a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo WatchMode mode, 92a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo bool persistent, 93a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo const Closure &task) { 94a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // base::MessageLoopForIO CHECKS that "fd >= 0", so we handle that case here. 95a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (fd < 0) 96a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return MessageLoop::kTaskIdNull; 97a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 98a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo base::MessageLoopForIO::Mode base_mode = base::MessageLoopForIO::WATCH_READ; 99a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo switch (mode) { 100a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo case MessageLoop::kWatchRead: 101a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo base_mode = base::MessageLoopForIO::WATCH_READ; 102a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo break; 103a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo case MessageLoop::kWatchWrite: 104a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo base_mode = base::MessageLoopForIO::WATCH_WRITE; 105a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo break; 106a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo default: 107a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return MessageLoop::kTaskIdNull; 108a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 109a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 110a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo TaskId task_id = NextTaskId(); 111a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo auto it_bool = io_tasks_.emplace( 112a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo std::piecewise_construct, 113a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo std::forward_as_tuple(task_id), 11407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo std::forward_as_tuple( 11507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo from_here, this, task_id, fd, base_mode, persistent, task)); 116a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // This should always insert a new element. 117a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo DCHECK(it_bool.second); 11807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo bool scheduled = it_bool.first->second.StartWatching(); 119a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo DVLOG_LOC(from_here, 1) 120a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << "Watching fd " << fd << " for " 121a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << (mode == MessageLoop::kWatchRead ? "reading" : "writing") 122a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << (persistent ? " persistently" : " just once") 123a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << " as task_id " << task_id 124a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << (scheduled ? " successfully" : " failed."); 125a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 126a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (!scheduled) { 127a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo io_tasks_.erase(task_id); 128a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return MessageLoop::kTaskIdNull; 129a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 130d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 131d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // Determine if the passed fd is the binder file descriptor. For that, we need 132d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // to check that is a special char device and that the major and minor device 133d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // numbers match. The binder file descriptor can't be removed and added back 134d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // to an epoll group when there's work available to be done by the file 135d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // descriptor due to bugs in the binder driver (b/26524111) when used with 136d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // epoll. Therefore, we flag the binder fd and never attempt to remove it. 137d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // This may cause the binder file descriptor to be attended with higher 138d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // priority and cause starvation of other events. 139d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo struct stat buf; 140d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo if (fstat(fd, &buf) == 0 && 141d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo S_ISCHR(buf.st_mode) && 142d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo major(buf.st_rdev) == MISC_MAJOR && 143d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo minor(buf.st_rdev) == GetBinderMinor()) { 144d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo it_bool.first->second.RunImmediately(); 145d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo } 146d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 147a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return task_id; 148a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 149a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 150a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymobool BaseMessageLoop::CancelTask(TaskId task_id) { 151a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (task_id == kTaskIdNull) 152a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return false; 153a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo auto delayed_task_it = delayed_tasks_.find(task_id); 154a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (delayed_task_it == delayed_tasks_.end()) { 155a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // This might be an IOTask then. 156a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo auto io_task_it = io_tasks_.find(task_id); 157a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (io_task_it == io_tasks_.end()) 158a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return false; 15907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo return io_task_it->second.CancelTask(); 160a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 161a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // A DelayedTask was found for this task_id at this point. 162a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 163a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // Check if the callback was already canceled but we have the entry in 164a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // delayed_tasks_ since it didn't fire yet in the message loop. 165a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (delayed_task_it->second.closure.is_null()) 166a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return false; 167a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 168a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo DVLOG_LOC(delayed_task_it->second.location, 1) 169a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << "Removing task_id " << task_id << " scheduled from this location."; 170a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // We reset to closure to a null Closure to release all the resources 171a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // used by this closure at this point, but we don't remove the task_id from 172a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // delayed_tasks_ since we can't tell base::MessageLoopForIO to not run it. 173a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo delayed_task_it->second.closure = Closure(); 174a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 175a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return true; 176a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 177a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 178a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymobool BaseMessageLoop::RunOnce(bool may_block) { 179a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo run_once_ = true; 18030ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo base::RunLoop run_loop; // Uses the base::MessageLoopForIO implicitly. 18130ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo base_run_loop_ = &run_loop; 182a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (!may_block) 18330ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo run_loop.RunUntilIdle(); 184a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo else 18530ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo run_loop.Run(); 18630ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo base_run_loop_ = nullptr; 187a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // If the flag was reset to false, it means a closure was run. 188a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (!run_once_) 189a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return true; 190a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 191a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo run_once_ = false; 192a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return false; 193a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 194a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 195a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymovoid BaseMessageLoop::Run() { 19630ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo base::RunLoop run_loop; // Uses the base::MessageLoopForIO implicitly. 19730ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo base_run_loop_ = &run_loop; 19830ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo run_loop.Run(); 19930ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo base_run_loop_ = nullptr; 200a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 201a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 202a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymovoid BaseMessageLoop::BreakLoop() { 20330ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo if (base_run_loop_ == nullptr) { 20430ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo DVLOG(1) << "Message loop not running, ignoring BreakLoop()."; 20530ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo return; // Message loop not running, nothing to do. 20630ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo } 20730ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo base_run_loop_->Quit(); 20830ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo} 20930ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo 21030ef318cd1d94e896a277324c68b89798e3dbbddAlex DeymoClosure BaseMessageLoop::QuitClosure() const { 21130ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo if (base_run_loop_ == nullptr) 21230ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo return base::Bind(&base::DoNothing); 21330ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo return base_run_loop_->QuitClosure(); 214a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 215a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 216a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoMessageLoop::TaskId BaseMessageLoop::NextTaskId() { 217a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo TaskId res; 218a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo do { 219a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo res = ++last_id_; 220a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // We would run out of memory before we run out of task ids. 221a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } while (!res || 222a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo delayed_tasks_.find(res) != delayed_tasks_.end() || 223a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo io_tasks_.find(res) != io_tasks_.end()); 224a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo return res; 225a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 226a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 227a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymovoid BaseMessageLoop::OnRanPostedTask(MessageLoop::TaskId task_id) { 228a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo auto task_it = delayed_tasks_.find(task_id); 229a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo DCHECK(task_it != delayed_tasks_.end()); 230a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (!task_it->second.closure.is_null()) { 231a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo DVLOG_LOC(task_it->second.location, 1) 232a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << "Running delayed task_id " << task_id 233a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo << " scheduled from this location."; 234a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // Mark the task as canceled while we are running it so CancelTask returns 235a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // false. 236a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo Closure closure = std::move(task_it->second.closure); 237a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo task_it->second.closure = Closure(); 238a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo closure.Run(); 239a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 240a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // If the |run_once_| flag is set, it is because we are instructed to run 241a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // only once callback. 242a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (run_once_) { 243a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo run_once_ = false; 24430ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo BreakLoop(); 245a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 246a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 247a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo delayed_tasks_.erase(task_it); 248a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 249a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 25007c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::OnFileReadyPostedTask(MessageLoop::TaskId task_id) { 25107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo auto task_it = io_tasks_.find(task_id); 25207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // Even if this task was canceled while we were waiting in the message loop 25307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // for this method to run, the entry in io_tasks_ should still be present, but 25407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // won't do anything. 25507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo DCHECK(task_it != io_tasks_.end()); 25607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo task_it->second.OnFileReadyPostedTask(); 25707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo} 25807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo 259d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymoint BaseMessageLoop::ParseBinderMinor( 260d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo const std::string& file_contents) { 261d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo int result = kInvalidMinor; 262d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // Split along '\n', then along the ' '. Note that base::SplitString trims all 263d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // white spaces at the beginning and end after splitting. 264d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo std::vector<std::string> lines; 265d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo base::SplitString(file_contents, '\n', &lines); 266d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo for (const std::string& line : lines) { 267d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo if (line.empty()) 268d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo continue; 269d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo std::string number; 270d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo std::string name; 271d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo if (!string_utils::SplitAtFirst(line, " ", &number, &name, false)) 272d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo continue; 273d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 274d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo if (name == kBinderDriverName && base::StringToInt(number, &result)) 275d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo break; 276d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo } 277d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo return result; 278d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo} 279d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 280d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymounsigned int BaseMessageLoop::GetBinderMinor() { 281d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo if (binder_minor_ != kUninitializedMinor) 282d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo return binder_minor_; 283d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 284d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo std::string proc_misc; 285d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo if (!base::ReadFileToString(base::FilePath(kMiscMinorPath), &proc_misc)) 286d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo return binder_minor_; 287d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo binder_minor_ = ParseBinderMinor(proc_misc); 288d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo return binder_minor_; 289d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo} 290d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 291a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex DeymoBaseMessageLoop::IOTask::IOTask(const tracked_objects::Location& location, 292a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo BaseMessageLoop* loop, 293a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo MessageLoop::TaskId task_id, 29407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo int fd, 29507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo base::MessageLoopForIO::Mode base_mode, 296a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo bool persistent, 297a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo const Closure& task) 298a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo : location_(location), loop_(loop), task_id_(task_id), 29907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo fd_(fd), base_mode_(base_mode), persistent_(persistent), closure_(task) {} 300a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 30107c1779e51680364060f3ec289249869ac7bc5caAlex Deymobool BaseMessageLoop::IOTask::StartWatching() { 30207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo return loop_->base_loop_->WatchFileDescriptor( 30307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo fd_, persistent_, base_mode_, &fd_watcher_, this); 304a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 305a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 30607c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::IOTask::StopWatching() { 30707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // This is safe to call even if we are not watching for it. 30807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo fd_watcher_.StopWatchingFileDescriptor(); 30907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo} 31007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo 31107c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::IOTask::OnFileCanReadWithoutBlocking(int /* fd */) { 31207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo OnFileReady(); 31307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo} 31407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo 31507c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::IOTask::OnFileCanWriteWithoutBlocking(int /* fd */) { 31607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo OnFileReady(); 31707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo} 31807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo 31907c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::IOTask::OnFileReady() { 320d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // For file descriptors marked with the immediate_run flag, we don't call 321d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // StopWatching() and wait, instead we dispatch the callback immediately. 322d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo if (immediate_run_) { 323d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo posted_task_pending_ = true; 324d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo OnFileReadyPostedTask(); 325d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo return; 326d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo } 327d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo 32807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // When the file descriptor becomes available we stop watching for it and 32907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // schedule a task to run the callback from the main loop. The callback will 330d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // run using the same scheduler used to run other delayed tasks, avoiding 33107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // starvation of the available posted tasks if there are file descriptors 33207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // always available. The new posted task will use the same TaskId as the 33307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // current file descriptor watching task an could be canceled in either state, 33407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // when waiting for the file descriptor or waiting in the main loop. 33507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo StopWatching(); 33607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo bool base_scheduled = loop_->base_loop_->task_runner()->PostTask( 33707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo location_, 33807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo base::Bind(&BaseMessageLoop::OnFileReadyPostedTask, 33907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo loop_->weak_ptr_factory_.GetWeakPtr(), 34007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo task_id_)); 34107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo posted_task_pending_ = true; 34207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo if (base_scheduled) { 34307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo DVLOG_LOC(location_, 1) 34407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo << "Dispatching task_id " << task_id_ << " for " 34507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo << (base_mode_ == base::MessageLoopForIO::WATCH_READ ? 34607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo "reading" : "writing") 34707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo << " file descriptor " << fd_ << ", scheduled from this location."; 34807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo } else { 34907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // In the rare case that PostTask() fails, we fall back to run it directly. 35007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // This would indicate a bigger problem with the message loop setup. 35107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo LOG(ERROR) << "Error on base::MessageLoopForIO::PostTask()."; 35207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo OnFileReadyPostedTask(); 35307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo } 354a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 355a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 35607c1779e51680364060f3ec289249869ac7bc5caAlex Deymovoid BaseMessageLoop::IOTask::OnFileReadyPostedTask() { 357a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // We can't access |this| after running the |closure_| since it could call 358a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // CancelTask on its own task_id, so we copy the members we need now. 359a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo BaseMessageLoop* loop_ptr = loop_; 36007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo DCHECK(posted_task_pending_ = true); 36107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo posted_task_pending_ = false; 36207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo 36307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // If this task was already canceled, the closure will be null and there is 36407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // nothing else to do here. This execution doesn't count a step for RunOnce() 36507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // unless we have a callback to run. 36607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo if (closure_.is_null()) { 36707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo loop_->io_tasks_.erase(task_id_); 36807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo return; 36907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo } 370a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 371a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo DVLOG_LOC(location_, 1) 37207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo << "Running task_id " << task_id_ << " for " 37307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo << (base_mode_ == base::MessageLoopForIO::WATCH_READ ? 37407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo "reading" : "writing") 37507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo << " file descriptor " << fd_ << ", scheduled from this location."; 376a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 377a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (persistent_) { 378a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // In the persistent case we just run the callback. If this callback cancels 37907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // the task id, we can't access |this| anymore, so we re-start watching the 380d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // file descriptor before running the callback, unless this is a fd where 381d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo // we didn't stop watching the file descriptor when it became available. 382d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo if (!immediate_run_) 383d671746a66d87edf9598cfbe077b3430e50a09d3Alex Deymo StartWatching(); 384a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo closure_.Run(); 385a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } else { 386a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // This will destroy |this|, the fd_watcher and therefore stop watching this 387a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // file descriptor. 388a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo Closure closure_copy = std::move(closure_); 389a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo loop_->io_tasks_.erase(task_id_); 390a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo // Run the closure from the local copy we just made. 391a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo closure_copy.Run(); 392a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 393a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 394a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo if (loop_ptr->run_once_) { 395a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo loop_ptr->run_once_ = false; 39630ef318cd1d94e896a277324c68b89798e3dbbddAlex Deymo loop_ptr->BreakLoop(); 397a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo } 398a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo} 399a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo 40007c1779e51680364060f3ec289249869ac7bc5caAlex Deymobool BaseMessageLoop::IOTask::CancelTask() { 40107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo if (closure_.is_null()) 40207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo return false; 40307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo 40407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo DVLOG_LOC(location_, 1) 40507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo << "Removing task_id " << task_id_ << " scheduled from this location."; 40607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo 40707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo if (!posted_task_pending_) { 40807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // Destroying the FileDescriptorWatcher implicitly stops watching the file 40907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // descriptor. This will delete our instance. 41007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo loop_->io_tasks_.erase(task_id_); 41107c1779e51680364060f3ec289249869ac7bc5caAlex Deymo return true; 41207c1779e51680364060f3ec289249869ac7bc5caAlex Deymo } 41307c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // The IOTask is waiting for the message loop to run its delayed task, so 41407c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // it is not watching for the file descriptor. We release the closure 41507c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // resources now but keep the IOTask instance alive while we wait for the 41607c1779e51680364060f3ec289249869ac7bc5caAlex Deymo // callback to run and delete the IOTask. 41707c1779e51680364060f3ec289249869ac7bc5caAlex Deymo closure_ = Closure(); 41807c1779e51680364060f3ec289249869ac7bc5caAlex Deymo return true; 41907c1779e51680364060f3ec289249869ac7bc5caAlex Deymo} 42007c1779e51680364060f3ec289249869ac7bc5caAlex Deymo 4219ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko} // namespace brillo 422