0

[tracing] Add IOHandler::OnIOCompleted trace event

Without this event, BrowserThread::IO can appear idle in traces while
it's actually processing native events.

IOCompletion being Windows-only, other platforms will need to be
implemented separately in their own way once this has proven useful.

Example trace with this CL : https://snipboard.io/93MeYg.jpg
(green toplevel bars are the new event)

Also took advantage of this to drive-by cleanup some old style
construction paradigms in old code.

R=fdoray@chromium.org

Bug: 899897
Change-Id: I0688556413687896b880c172a00d2c4eb8c1b07e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2134772
Reviewed-by: Ken Rockot <rockot@google.com>
Reviewed-by: Gary Kacmarcik <garykac@chromium.org>
Reviewed-by: Maksim Orlovich <morlovich@chromium.org>
Reviewed-by: François Doray <fdoray@chromium.org>
Auto-Submit: Gabriel Charette <gab@chromium.org>
Commit-Queue: Gabriel Charette <gab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#757988}
This commit is contained in:
Gabriel Charette
2020-04-09 20:31:10 +00:00
committed by Commit Bot
parent d0dd50886b
commit 96d5c648d4
11 changed files with 61 additions and 61 deletions

@ -387,7 +387,7 @@ class TestIOHandler : public MessagePumpForIO::IOHandler {
}; };
TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait) TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait)
: signal_(signal), wait_(wait) { : MessagePumpForIO::IOHandler(FROM_HERE), signal_(signal), wait_(wait) {
memset(buffer_, 0, sizeof(buffer_)); memset(buffer_, 0, sizeof(buffer_));
file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,

@ -544,6 +544,11 @@ MessagePumpForIO::IOContext::IOContext() {
memset(&overlapped, 0, sizeof(overlapped)); memset(&overlapped, 0, sizeof(overlapped));
} }
MessagePumpForIO::IOHandler::IOHandler(const Location& from_here)
: io_handler_location_(from_here) {}
MessagePumpForIO::IOHandler::~IOHandler() = default;
MessagePumpForIO::MessagePumpForIO() { MessagePumpForIO::MessagePumpForIO() {
port_.Set(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, port_.Set(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr,
reinterpret_cast<ULONG_PTR>(nullptr), 1)); reinterpret_cast<ULONG_PTR>(nullptr), 1));
@ -678,6 +683,9 @@ bool MessagePumpForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) {
// Save this item for later // Save this item for later
completed_io_.push_back(item); completed_io_.push_back(item);
} else { } else {
TRACE_EVENT2("base,toplevel", "IOHandler::OnIOCompleted", "dest_file",
item.handler->io_handler_location().file_name(), "dest_func",
item.handler->io_handler_location().function_name());
item.handler->OnIOCompleted(item.context, item.bytes_transfered, item.handler->OnIOCompleted(item.context, item.bytes_transfered,
item.error); item.error);
} }

@ -12,6 +12,7 @@
#include <memory> #include <memory>
#include "base/base_export.h" #include "base/base_export.h"
#include "base/location.h"
#include "base/message_loop/message_pump.h" #include "base/message_loop/message_pump.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/optional.h" #include "base/optional.h"
@ -198,7 +199,7 @@ class BASE_EXPORT MessagePumpForIO : public MessagePumpWin {
// //
// Typical use #1: // Typical use #1:
// class MyFile : public IOHandler { // class MyFile : public IOHandler {
// MyFile() { // MyFile() : IOHandler(FROM_HERE) {
// ... // ...
// message_pump->RegisterIOHandler(file_, this); // message_pump->RegisterIOHandler(file_, this);
// } // }
@ -228,9 +229,14 @@ class BASE_EXPORT MessagePumpForIO : public MessagePumpWin {
// message_pump->WaitForIOCompletion(INFINITE, this); // message_pump->WaitForIOCompletion(INFINITE, this);
// } // }
// //
class IOHandler { class BASE_EXPORT IOHandler {
public: public:
virtual ~IOHandler() {} explicit IOHandler(const Location& from_here);
virtual ~IOHandler();
IOHandler(const IOHandler&) = delete;
IOHandler& operator=(const IOHandler&) = delete;
// This will be called once the pending IO operation associated with // This will be called once the pending IO operation associated with
// |context| completes. |error| is the Win32 error code of the IO operation // |context| completes. |error| is the Win32 error code of the IO operation
// (ERROR_SUCCESS if there was no error). |bytes_transfered| will be zero // (ERROR_SUCCESS if there was no error). |bytes_transfered| will be zero
@ -238,6 +244,11 @@ class BASE_EXPORT MessagePumpForIO : public MessagePumpWin {
virtual void OnIOCompleted(IOContext* context, virtual void OnIOCompleted(IOContext* context,
DWORD bytes_transfered, DWORD bytes_transfered,
DWORD error) = 0; DWORD error) = 0;
const Location& io_handler_location() { return io_handler_location_; }
private:
const Location io_handler_location_;
}; };
MessagePumpForIO(); MessagePumpForIO();

@ -85,6 +85,7 @@ class ChannelWin : public Channel,
HandlePolicy handle_policy, HandlePolicy handle_policy,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
: Channel(delegate, handle_policy), : Channel(delegate, handle_policy),
base::MessagePumpForIO::IOHandler(FROM_HERE),
self_(this), self_(this),
io_task_runner_(io_task_runner) { io_task_runner_(io_task_runner) {
if (connection_params.server_endpoint().is_valid()) { if (connection_params.server_endpoint().is_valid()) {

@ -62,8 +62,8 @@ class FileStream::Context {
// file_stream_context_{win,posix}.cc. // file_stream_context_{win,posix}.cc.
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
explicit Context(const scoped_refptr<base::TaskRunner>& task_runner); explicit Context(scoped_refptr<base::TaskRunner> task_runner);
Context(base::File file, const scoped_refptr<base::TaskRunner>& task_runner); Context(base::File file, scoped_refptr<base::TaskRunner> task_runner);
#if defined(OS_WIN) #if defined(OS_WIN)
~Context() override; ~Context() override;
#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
@ -172,7 +172,7 @@ class FileStream::Context {
// Deletes an orphaned context. // Deletes an orphaned context.
void DeleteOrphanedContext(); void DeleteOrphanedContext();
// The ReadFile call on Windows can execute synchonously at times. // The ReadFile call on Windows can execute synchronously at times.
// http://support.microsoft.com/kb/156932. This ends up blocking the calling // http://support.microsoft.com/kb/156932. This ends up blocking the calling
// thread which is undesirable. To avoid this we execute the ReadFile call // thread which is undesirable. To avoid this we execute the ReadFile call
// on a worker thread. // on a worker thread.
@ -217,10 +217,10 @@ class FileStream::Context {
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
base::File file_; base::File file_;
bool async_in_progress_; bool async_in_progress_ = false;
bool orphaned_; bool orphaned_ = false;
scoped_refptr<base::TaskRunner> task_runner_; const scoped_refptr<base::TaskRunner> task_runner_;
#if defined(OS_WIN) #if defined(OS_WIN)
base::MessagePumpForIO::IOContext io_context_; base::MessagePumpForIO::IOContext io_context_;
@ -228,16 +228,16 @@ class FileStream::Context {
scoped_refptr<IOBuffer> in_flight_buf_; scoped_refptr<IOBuffer> in_flight_buf_;
// This flag is set to true when we receive a Read request which is queued to // This flag is set to true when we receive a Read request which is queued to
// the thread pool. // the thread pool.
bool async_read_initiated_; bool async_read_initiated_ = false;
// This flag is set to true when we receive a notification ReadAsyncResult() // This flag is set to true when we receive a notification ReadAsyncResult()
// on the calling thread which indicates that the asynchronous Read // on the calling thread which indicates that the asynchronous Read
// operation is complete. // operation is complete.
bool async_read_completed_; bool async_read_completed_ = false;
// This flag is set to true when we receive an IO completion notification for // This flag is set to true when we receive an IO completion notification for
// an asynchonously initiated Read operaton. OnIOComplete(). // an asynchronously initiated Read operation. OnIOComplete().
bool io_complete_for_read_received_; bool io_complete_for_read_received_ = false;
// Tracks the result of the IO completion operation. Set in OnIOComplete. // Tracks the result of the IO completion operation. Set in OnIOComplete.
int result_; int result_ = 0;
#endif #endif
DISALLOW_COPY_AND_ASSIGN(Context); DISALLOW_COPY_AND_ASSIGN(Context);

@ -21,18 +21,12 @@
namespace net { namespace net {
FileStream::Context::Context(const scoped_refptr<base::TaskRunner>& task_runner) FileStream::Context::Context(scoped_refptr<base::TaskRunner> task_runner)
: async_in_progress_(false), : Context(base::File(), std::move(task_runner)) {}
orphaned_(false),
task_runner_(task_runner) {
}
FileStream::Context::Context(base::File file, FileStream::Context::Context(base::File file,
const scoped_refptr<base::TaskRunner>& task_runner) scoped_refptr<base::TaskRunner> task_runner)
: file_(std::move(file)), : file_(std::move(file)), task_runner_(std::move(task_runner)) {}
async_in_progress_(false),
orphaned_(false),
task_runner_(task_runner) {}
FileStream::Context::~Context() = default; FileStream::Context::~Context() = default;

@ -38,25 +38,14 @@ void IncrementOffset(OVERLAPPED* overlapped, DWORD count) {
} // namespace } // namespace
FileStream::Context::Context(const scoped_refptr<base::TaskRunner>& task_runner) FileStream::Context::Context(scoped_refptr<base::TaskRunner> task_runner)
: async_in_progress_(false), : Context(base::File(), std::move(task_runner)) {}
orphaned_(false),
task_runner_(task_runner),
async_read_initiated_(false),
async_read_completed_(false),
io_complete_for_read_received_(false),
result_(0) {}
FileStream::Context::Context(base::File file, FileStream::Context::Context(base::File file,
const scoped_refptr<base::TaskRunner>& task_runner) scoped_refptr<base::TaskRunner> task_runner)
: file_(std::move(file)), : base::MessagePumpForIO::IOHandler(FROM_HERE),
async_in_progress_(false), file_(std::move(file)),
orphaned_(false), task_runner_(std::move(task_runner)) {
task_runner_(task_runner),
async_read_initiated_(false),
async_read_completed_(false),
io_complete_for_read_received_(false),
result_(0) {
if (file_.IsValid()) { if (file_.IsValid()) {
DCHECK(file_.async()); DCHECK(file_.async());
OnFileOpened(); OnFileOpened();

@ -40,7 +40,7 @@ static_assert(offsetof(MyOverlapped, context_) == 0,
class CompletionHandler : public base::MessagePumpForIO::IOHandler, class CompletionHandler : public base::MessagePumpForIO::IOHandler,
public base::RefCounted<CompletionHandler> { public base::RefCounted<CompletionHandler> {
public: public:
CompletionHandler() = default; CompletionHandler() : base::MessagePumpForIO::IOHandler(FROM_HERE) {}
static CompletionHandler* Get(); static CompletionHandler* Get();
private: private:

@ -114,34 +114,34 @@ class WtsSessionProcessDelegate::Core
void ReportProcessLaunched(base::win::ScopedHandle worker_process); void ReportProcessLaunched(base::win::ScopedHandle worker_process);
// The task runner all public methods of this class should be called on. // The task runner all public methods of this class should be called on.
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
// The task runner serving job object notifications. // The task runner serving job object notifications.
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
// The server end of the IPC channel used to communicate to the worker // The server end of the IPC channel used to communicate to the worker
// process. // process.
std::unique_ptr<IPC::ChannelProxy> channel_; std::unique_ptr<IPC::ChannelProxy> channel_;
// Security descriptor (as SDDL) to be applied to |channel_|. // Security descriptor (as SDDL) to be applied to |channel_|.
std::string channel_security_; const std::string channel_security_;
WorkerProcessLauncher* event_handler_; WorkerProcessLauncher* event_handler_ = nullptr;
// The job object used to control the lifetime of child processes. // The job object used to control the lifetime of child processes.
base::win::ScopedHandle job_; base::win::ScopedHandle job_;
// True if the worker process should be launched elevated. // True if the worker process should be launched elevated.
bool launch_elevated_; const bool launch_elevated_;
// True if a laucnh attemp is pending. // True if a launch attempt is pending.
bool launch_pending_; bool launch_pending_ = false;
// The token to be used to launch a process in a different session. // The token to be used to launch a process in a different session.
base::win::ScopedHandle session_token_; base::win::ScopedHandle session_token_;
// Command line of the launched process. // Command line of the launched process.
std::unique_ptr<base::CommandLine> target_command_; const std::unique_ptr<base::CommandLine> target_command_;
// The handle of the worker process, if launched. // The handle of the worker process, if launched.
base::win::ScopedHandle worker_process_; base::win::ScopedHandle worker_process_;
@ -167,12 +167,11 @@ WtsSessionProcessDelegate::Core::Core(
std::unique_ptr<base::CommandLine> target_command, std::unique_ptr<base::CommandLine> target_command,
bool launch_elevated, bool launch_elevated,
const std::string& channel_security) const std::string& channel_security)
: caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), : base::MessagePumpForIO::IOHandler(FROM_HERE),
io_task_runner_(io_task_runner), caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
io_task_runner_(std::move(io_task_runner)),
channel_security_(channel_security), channel_security_(channel_security),
event_handler_(nullptr),
launch_elevated_(launch_elevated), launch_elevated_(launch_elevated),
launch_pending_(false),
target_command_(std::move(target_command)) {} target_command_(std::move(target_command)) {}
bool WtsSessionProcessDelegate::Core::Initialize(uint32_t session_id) { bool WtsSessionProcessDelegate::Core::Initialize(uint32_t session_id) {

@ -358,9 +358,7 @@ SerialIoHandlerWin::SerialIoHandlerWin(
const base::FilePath& port, const base::FilePath& port,
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
: SerialIoHandler(port, std::move(ui_thread_task_runner)), : SerialIoHandler(port, std::move(ui_thread_task_runner)),
event_mask_(0), base::MessagePumpForIO::IOHandler(FROM_HERE) {}
is_comm_pending_(false),
helper_(nullptr) {}
SerialIoHandlerWin::~SerialIoHandlerWin() { SerialIoHandlerWin::~SerialIoHandlerWin() {
ui_thread_task_runner()->DeleteSoon(FROM_HERE, helper_); ui_thread_task_runner()->DeleteSoon(FROM_HERE, helper_);

@ -59,16 +59,16 @@ class SerialIoHandlerWin : public SerialIoHandler,
std::unique_ptr<base::MessagePumpForIO::IOContext> write_context_; std::unique_ptr<base::MessagePumpForIO::IOContext> write_context_;
// Asynchronous event mask state // Asynchronous event mask state
DWORD event_mask_; DWORD event_mask_ = 0;
// Indicates if a pending read is waiting on initial data arrival via // Indicates if a pending read is waiting on initial data arrival via
// WaitCommEvent, as opposed to waiting on actual ReadFile completion // WaitCommEvent, as opposed to waiting on actual ReadFile completion
// after a corresponding WaitCommEvent has completed. // after a corresponding WaitCommEvent has completed.
bool is_comm_pending_; bool is_comm_pending_ = false;
// The helper lives on the UI thread and holds a weak reference back to the // The helper lives on the UI thread and holds a weak reference back to the
// handler that owns it. // handler that owns it.
UiThreadHelper* helper_; UiThreadHelper* helper_ = nullptr;
base::WeakPtrFactory<SerialIoHandlerWin> weak_factory_{this}; base::WeakPtrFactory<SerialIoHandlerWin> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SerialIoHandlerWin); DISALLOW_COPY_AND_ASSIGN(SerialIoHandlerWin);