| Index: chrome/profiling/memlog_receiver_pipe_server_win.cc
|
| diff --git a/chrome/profiling/memlog_receiver_pipe_server_win.cc b/chrome/profiling/memlog_receiver_pipe_server_win.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cf426f4bf57a53b9dce2f819c829fe6bac0ef34b
|
| --- /dev/null
|
| +++ b/chrome/profiling/memlog_receiver_pipe_server_win.cc
|
| @@ -0,0 +1,84 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/profiling/memlog_receiver_pipe_server_win.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "chrome/common/profiling/memlog_stream.h"
|
| +
|
| +namespace profiling {
|
| +
|
| +namespace {
|
| +
|
| +// Use a large buffer for our pipe. We don't want the sender to block
|
| +// if at all possible since it will slow the app down quite a bit. Windows
|
| +// seemed to max out a 64K per read when testing larger sizes, so use that.
|
| +const int kBufferSize = 1024 * 64;
|
| +
|
| +} // namespace
|
| +
|
| +MemlogReceiverPipeServer::MemlogReceiverPipeServer(
|
| + base::TaskRunner* io_runner,
|
| + const std::string& pipe_id,
|
| + NewConnectionCallback on_new_conn)
|
| + : io_runner_(io_runner),
|
| + pipe_id_(base::ASCIIToUTF16(pipe_id)),
|
| + on_new_connection_(on_new_conn) {}
|
| +
|
| +MemlogReceiverPipeServer::~MemlogReceiverPipeServer() {
|
| + // TODO(brettw) we should ensure this destructor is not called when there are
|
| + // pending I/O operations as per RegisterIOHandler documentation.
|
| +}
|
| +
|
| +void MemlogReceiverPipeServer::Start() {
|
| + // TODO(brettw) this should perhaps not be async in case the subprocess
|
| + // launches and tries to connect before the first pipe instance is created.
|
| + io_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&MemlogReceiverPipeServer::ScheduleNewConnection, this, true));
|
| +}
|
| +
|
| +base::string16 MemlogReceiverPipeServer::GetPipeName() const {
|
| + base::string16 pipe_name(kWindowsPipePrefix);
|
| + pipe_name.append(pipe_id_);
|
| + return pipe_name;
|
| +}
|
| +
|
| +HANDLE MemlogReceiverPipeServer::CreatePipeInstance(bool first_instance) const {
|
| + base::string16 pipe_name = GetPipeName();
|
| +
|
| + DWORD open_mode = PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED;
|
| + if (first_instance)
|
| + open_mode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
|
| +
|
| + return ::CreateNamedPipe(
|
| + pipe_name.c_str(), open_mode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
|
| + PIPE_UNLIMITED_INSTANCES, kBufferSize, kBufferSize, 5000, NULL);
|
| +}
|
| +
|
| +void MemlogReceiverPipeServer::ScheduleNewConnection(bool first_instance) {
|
| + DCHECK(!current_);
|
| + // Need Unretained to avoid creating a reference cycle.
|
| + current_ = base::MakeUnique<MemlogReceiverPipe::CompletionThunk>(
|
| + CreatePipeInstance(first_instance),
|
| + base::BindRepeating(&MemlogReceiverPipeServer::OnIOCompleted,
|
| + base::Unretained(this)));
|
| + ::ConnectNamedPipe(current_->handle(), current_->overlapped());
|
| +}
|
| +
|
| +void MemlogReceiverPipeServer::OnIOCompleted(size_t bytes_transfered,
|
| + DWORD error) {
|
| + scoped_refptr<MemlogReceiverPipe> pipe(
|
| + new MemlogReceiverPipe(std::move(current_)));
|
| + ScheduleNewConnection(false);
|
| +
|
| + if (!on_new_connection_.is_null())
|
| + on_new_connection_.Run(pipe);
|
| + pipe->StartReadingOnIOThread();
|
| +}
|
| +
|
| +} // namespace profiling
|
|
|