| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/profiling/memlog_receiver_pipe_server_win.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/strings/utf_string_conversions.h" |
| 11 #include "chrome/common/profiling/memlog_stream.h" |
| 12 |
| 13 namespace profiling { |
| 14 |
| 15 namespace { |
| 16 |
| 17 // Use a large buffer for our pipe. We don't want the sender to block |
| 18 // if at all possible since it will slow the app down quite a bit. Windows |
| 19 // seemed to max out a 64K per read when testing larger sizes, so use that. |
| 20 const int kBufferSize = 1024 * 64; |
| 21 |
| 22 } // namespace |
| 23 |
| 24 MemlogReceiverPipeServer::MemlogReceiverPipeServer( |
| 25 base::TaskRunner* io_runner, |
| 26 const std::string& pipe_id, |
| 27 NewConnectionCallback on_new_conn) |
| 28 : io_runner_(io_runner), |
| 29 pipe_id_(base::ASCIIToUTF16(pipe_id)), |
| 30 on_new_connection_(on_new_conn) {} |
| 31 |
| 32 MemlogReceiverPipeServer::~MemlogReceiverPipeServer() { |
| 33 // TODO(brettw) we should ensure this destructor is not called when there are |
| 34 // pending I/O operations as per RegisterIOHandler documentation. |
| 35 } |
| 36 |
| 37 void MemlogReceiverPipeServer::Start() { |
| 38 // TODO(brettw) this should perhaps not be async in case the subprocess |
| 39 // launches and tries to connect before the first pipe instance is created. |
| 40 io_runner_->PostTask( |
| 41 FROM_HERE, |
| 42 base::Bind(&MemlogReceiverPipeServer::ScheduleNewConnection, this, true)); |
| 43 } |
| 44 |
| 45 base::string16 MemlogReceiverPipeServer::GetPipeName() const { |
| 46 base::string16 pipe_name(kWindowsPipePrefix); |
| 47 pipe_name.append(pipe_id_); |
| 48 return pipe_name; |
| 49 } |
| 50 |
| 51 HANDLE MemlogReceiverPipeServer::CreatePipeInstance(bool first_instance) const { |
| 52 base::string16 pipe_name = GetPipeName(); |
| 53 |
| 54 DWORD open_mode = PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED; |
| 55 if (first_instance) |
| 56 open_mode |= FILE_FLAG_FIRST_PIPE_INSTANCE; |
| 57 |
| 58 return ::CreateNamedPipe( |
| 59 pipe_name.c_str(), open_mode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, |
| 60 PIPE_UNLIMITED_INSTANCES, kBufferSize, kBufferSize, 5000, NULL); |
| 61 } |
| 62 |
| 63 void MemlogReceiverPipeServer::ScheduleNewConnection(bool first_instance) { |
| 64 DCHECK(!current_); |
| 65 // Need Unretained to avoid creating a reference cycle. |
| 66 current_ = base::MakeUnique<MemlogReceiverPipe::CompletionThunk>( |
| 67 CreatePipeInstance(first_instance), |
| 68 base::BindRepeating(&MemlogReceiverPipeServer::OnIOCompleted, |
| 69 base::Unretained(this))); |
| 70 ::ConnectNamedPipe(current_->handle(), current_->overlapped()); |
| 71 } |
| 72 |
| 73 void MemlogReceiverPipeServer::OnIOCompleted(size_t bytes_transfered, |
| 74 DWORD error) { |
| 75 scoped_refptr<MemlogReceiverPipe> pipe( |
| 76 new MemlogReceiverPipe(std::move(current_))); |
| 77 ScheduleNewConnection(false); |
| 78 |
| 79 if (!on_new_connection_.is_null()) |
| 80 on_new_connection_.Run(pipe); |
| 81 pipe->StartReadingOnIOThread(); |
| 82 } |
| 83 |
| 84 } // namespace profiling |
| OLD | NEW |