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)
: signal_(signal), wait_(wait) {
: MessagePumpForIO::IOHandler(FROM_HERE), signal_(signal), wait_(wait) {
memset(buffer_, 0, sizeof(buffer_));
file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,

@ -544,6 +544,11 @@ MessagePumpForIO::IOContext::IOContext() {
memset(&overlapped, 0, sizeof(overlapped));
}
MessagePumpForIO::IOHandler::IOHandler(const Location& from_here)
: io_handler_location_(from_here) {}
MessagePumpForIO::IOHandler::~IOHandler() = default;
MessagePumpForIO::MessagePumpForIO() {
port_.Set(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr,
reinterpret_cast<ULONG_PTR>(nullptr), 1));
@ -678,6 +683,9 @@ bool MessagePumpForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) {
// Save this item for later
completed_io_.push_back(item);
} 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.error);
}

@ -12,6 +12,7 @@
#include <memory>
#include "base/base_export.h"
#include "base/location.h"
#include "base/message_loop/message_pump.h"
#include "base/observer_list.h"
#include "base/optional.h"
@ -198,7 +199,7 @@ class BASE_EXPORT MessagePumpForIO : public MessagePumpWin {
//
// Typical use #1:
// class MyFile : public IOHandler {
// MyFile() {
// MyFile() : IOHandler(FROM_HERE) {
// ...
// message_pump->RegisterIOHandler(file_, this);
// }
@ -228,9 +229,14 @@ class BASE_EXPORT MessagePumpForIO : public MessagePumpWin {
// message_pump->WaitForIOCompletion(INFINITE, this);
// }
//
class IOHandler {
class BASE_EXPORT IOHandler {
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
// |context| completes. |error| is the Win32 error code of the IO operation
// (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,
DWORD bytes_transfered,
DWORD error) = 0;
const Location& io_handler_location() { return io_handler_location_; }
private:
const Location io_handler_location_;
};
MessagePumpForIO();

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

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

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

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

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

@ -114,34 +114,34 @@ class WtsSessionProcessDelegate::Core
void ReportProcessLaunched(base::win::ScopedHandle worker_process);
// 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.
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
// process.
std::unique_ptr<IPC::ChannelProxy> 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.
base::win::ScopedHandle job_;
// True if the worker process should be launched elevated.
bool launch_elevated_;
const bool launch_elevated_;
// True if a laucnh attemp is pending.
bool launch_pending_;
// True if a launch attempt is pending.
bool launch_pending_ = false;
// The token to be used to launch a process in a different session.
base::win::ScopedHandle session_token_;
// 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.
base::win::ScopedHandle worker_process_;
@ -167,12 +167,11 @@ WtsSessionProcessDelegate::Core::Core(
std::unique_ptr<base::CommandLine> target_command,
bool launch_elevated,
const std::string& channel_security)
: caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
io_task_runner_(io_task_runner),
: base::MessagePumpForIO::IOHandler(FROM_HERE),
caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
io_task_runner_(std::move(io_task_runner)),
channel_security_(channel_security),
event_handler_(nullptr),
launch_elevated_(launch_elevated),
launch_pending_(false),
target_command_(std::move(target_command)) {}
bool WtsSessionProcessDelegate::Core::Initialize(uint32_t session_id) {

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

@ -59,16 +59,16 @@ class SerialIoHandlerWin : public SerialIoHandler,
std::unique_ptr<base::MessagePumpForIO::IOContext> write_context_;
// Asynchronous event mask state
DWORD event_mask_;
DWORD event_mask_ = 0;
// Indicates if a pending read is waiting on initial data arrival via
// WaitCommEvent, as opposed to waiting on actual ReadFile completion
// 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
// handler that owns it.
UiThreadHelper* helper_;
UiThreadHelper* helper_ = nullptr;
base::WeakPtrFactory<SerialIoHandlerWin> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SerialIoHandlerWin);