Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1446)

Unified Diff: mojo/edk/system/raw_channel_win.cc

Issue 1649633002: Remove files that are no longer used in the Port EDK. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/edk/system/raw_channel_unittest.cc ('k') | mojo/edk/system/routed_raw_channel.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/edk/system/raw_channel_win.cc
diff --git a/mojo/edk/system/raw_channel_win.cc b/mojo/edk/system/raw_channel_win.cc
deleted file mode 100644
index 71b69d4af4e5fcd3e13d060328d22ac1160c1b80..0000000000000000000000000000000000000000
--- a/mojo/edk/system/raw_channel_win.cc
+++ /dev/null
@@ -1,787 +0,0 @@
-// Copyright 2013 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 "mojo/edk/system/raw_channel.h"
-
-#include <windows.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/process/process.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/windows_version.h"
-#include "mojo/edk/embedder/embedder_internal.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/system/broker.h"
-#include "mojo/edk/system/transport_data.h"
-#include "mojo/public/cpp/system/macros.h"
-
-#define STATUS_CANCELLED 0xC0000120
-#define STATUS_PIPE_BROKEN 0xC000014B
-
-namespace mojo {
-namespace edk {
-
-namespace {
-
-class VistaOrHigherFunctions {
- public:
- VistaOrHigherFunctions()
- : is_vista_or_higher_(
- base::win::GetVersion() >= base::win::VERSION_VISTA),
- cancel_io_ex_(nullptr),
- get_file_information_by_handle_ex_(nullptr) {
- if (!is_vista_or_higher_)
- return;
-
- HMODULE module = GetModuleHandleW(L"kernel32.dll");
- cancel_io_ex_ =
- reinterpret_cast<CancelIoExFunc>(GetProcAddress(module, "CancelIoEx"));
- DCHECK(cancel_io_ex_);
-
- get_file_information_by_handle_ex_ =
- reinterpret_cast<GetFileInformationByHandleExFunc>(
- GetProcAddress(module, "GetFileInformationByHandleEx"));
- DCHECK(get_file_information_by_handle_ex_);
- }
-
- bool is_vista_or_higher() const { return is_vista_or_higher_; }
-
- BOOL CancelIoEx(HANDLE handle, LPOVERLAPPED overlapped) {
- return cancel_io_ex_(handle, overlapped);
- }
-
- BOOL GetFileInformationByHandleEx(HANDLE handle,
- FILE_INFO_BY_HANDLE_CLASS file_info_class,
- LPVOID file_info,
- DWORD buffer_size) {
- return get_file_information_by_handle_ex_(
- handle, file_info_class, file_info, buffer_size);
- }
-
- private:
- using CancelIoExFunc = BOOL(WINAPI*)(HANDLE, LPOVERLAPPED);
- using GetFileInformationByHandleExFunc = BOOL(WINAPI*)(
- HANDLE, FILE_INFO_BY_HANDLE_CLASS, LPVOID, DWORD);
-
- bool is_vista_or_higher_;
- CancelIoExFunc cancel_io_ex_;
- GetFileInformationByHandleExFunc get_file_information_by_handle_ex_;
-};
-
-base::LazyInstance<VistaOrHigherFunctions> g_vista_or_higher_functions =
- LAZY_INSTANCE_INITIALIZER;
-
-void CancelOnIO(HANDLE handle, base::WaitableEvent* event) {
- CancelIo(handle);
- event->Signal();
-}
-
-class RawChannelWin final : public RawChannel {
- public:
- RawChannelWin(ScopedPlatformHandle handle)
- : handle_(handle.Pass()), io_handler_(nullptr) {
- DCHECK(handle_.is_valid());
- }
- ~RawChannelWin() override {
- DCHECK(!io_handler_);
- }
-
- PlatformHandle GetHandle() {
- // We need to acquire write_lock() and not read_lock() to avoid deadlocks.
- // The reason is that we acquire read_lock() when calling the delegate,
- // which in turn is a Dispatcher that has acquired its lock(). But it could
- // already be in its lock() and calling IsOtherEndOf (i.e. this method).
- base::AutoLock locker(write_lock());
- if (handle_.is_valid())
- return handle_.get();
-
- if (!io_handler_)
- return PlatformHandle();
-
- return PlatformHandle(io_handler_->handle());
- }
-
- private:
- // RawChannelIOHandler receives OS notifications for I/O completion. Currently
- // this object is only used on the IO thread, other than ReleaseHandle. But
- // there's nothing preventing using this on other threads.
- //
- // It manages its own destruction. Destruction happens on the I/O thread when
- // all the following conditions are satisfied:
- // - |DetachFromOwnerNoLock()| has been called;
- // - there is no pending read;
- // - there is no pending write.
- class RawChannelIOHandler {
- public:
- RawChannelIOHandler(RawChannelWin* owner,
- ScopedPlatformHandle handle)
- : handle_(handle.Pass()),
- io_task_runner_(internal::g_io_thread_task_runner),
- owner_(owner),
- suppress_self_destruct_(false),
- pending_read_(false),
- pending_write_(false),
- platform_handles_written_(0),
- read_event_(CreateEvent(NULL, FALSE, FALSE, NULL)),
- write_event_(CreateEvent(NULL, FALSE, FALSE, NULL)),
- read_wait_object_(NULL),
- write_wait_object_(NULL),
- read_event_signalled_(false),
- write_event_signalled_(false),
- weak_ptr_factory_(this) {
- memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped));
- memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped));
- read_context_.overlapped.hEvent = read_event_.Get();
- write_context_.overlapped.hEvent = write_event_.Get();
-
- this_weakptr_ = weak_ptr_factory_.GetWeakPtr();
- RegisterWaitForSingleObject(&read_wait_object_, read_event_.Get(),
- ReadCompleted, this, INFINITE, WT_EXECUTEINWAITTHREAD);
- RegisterWaitForSingleObject(&write_wait_object_, write_event_.Get(),
- WriteCompleted, this, INFINITE, WT_EXECUTEINWAITTHREAD);
- }
-
- ~RawChannelIOHandler() {
- if (read_wait_object_)
- UnregisterWaitEx(read_wait_object_, INVALID_HANDLE_VALUE);
-
- if (write_wait_object_)
- UnregisterWaitEx(write_wait_object_, INVALID_HANDLE_VALUE);
- DCHECK(ShouldSelfDestruct() ||
- !base::MessageLoop::current()->is_running());
- }
-
- HANDLE handle() const { return handle_.get().handle; }
-
- // The following methods are only called by the owner on the I/O thread.
- bool pending_read() const {
- DCHECK(owner_);
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
- return pending_read_;
- }
-
- base::MessageLoopForIO::IOContext* read_context() {
- DCHECK(owner_);
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
- return &read_context_;
- }
-
- // Instructs the object to wait for an OnObjectSignaled notification.
- void OnPendingReadStarted() {
- DCHECK(owner_);
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
- DCHECK(!pending_read_);
- pending_read_ = true;
- read_event_signalled_ = false;
- }
-
- // The following methods are only called by the owner under
- // |owner_->write_lock()|.
- bool pending_write_no_lock() const {
- DCHECK(owner_);
- owner_->write_lock().AssertAcquired();
- return pending_write_;
- }
-
- base::MessageLoopForIO::IOContext* write_context_no_lock() {
- DCHECK(owner_);
- owner_->write_lock().AssertAcquired();
- return &write_context_;
- }
-
- // Instructs the object to wait for an OnObjectSignaled notification.
- void OnPendingWriteStartedNoLock(size_t platform_handles_written) {
- DCHECK(owner_);
- owner_->write_lock().AssertAcquired();
- DCHECK(!pending_write_);
- pending_write_ = true;
- write_event_signalled_ = false;
- platform_handles_written_ = platform_handles_written;
- }
-
- // Must be called on the I/O thread under read and write locks.
- // After this call, the owner must not make any further calls on this
- // object, and therefore the object is used on the I/O thread exclusively
- // (if it stays alive).
- void DetachFromOwnerNoLock(scoped_ptr<ReadBuffer> read_buffer,
- scoped_ptr<WriteBuffer> write_buffer) {
- DCHECK(owner_);
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
- owner_->read_lock().AssertAcquired();
- owner_->write_lock().AssertAcquired();
-
- // If read/write is pending, we have to retain the corresponding buffer.
- if (pending_read_)
- preserved_read_buffer_after_detach_ = read_buffer.Pass();
- if (pending_write_)
- preserved_write_buffer_after_detach_ = write_buffer.Pass();
-
- owner_ = nullptr;
- // On shutdown, the message loop won't be running. Since we'll never get
- // notifications after this point, delete the object to avoid leaks.
- if (ShouldSelfDestruct() || !base::MessageLoop::current()->is_running())
- delete this;
- }
-
- ScopedPlatformHandle ReleaseHandle(
- std::vector<char>* serialized_read_buffer,
- std::vector<char>* serialized_write_buffer,
- bool* write_error) {
- // Cancel pending IO calls.
- bool is_xp = false;
- if (g_vista_or_higher_functions.Get().is_vista_or_higher()) {
- g_vista_or_higher_functions.Get().CancelIoEx(handle(), nullptr);
- } else {
- is_xp = true;
- if (pending_read_) {
- if (internal::g_io_thread_task_runner->RunsTasksOnCurrentThread()) {
- CancelIo(handle());
- } else {
- base::WaitableEvent event(false, false);
- internal::g_io_thread_task_runner->PostTask(
- FROM_HERE,
- base::Bind(&CancelOnIO, handle(), &event));
- event.Wait();
- }
- }
- }
-
- size_t additional_bytes_read = 0;
- bool got_read_error = false;
- if (pending_read_) {
- bool wait = false;
- UnregisterWaitEx(read_wait_object_, INVALID_HANDLE_VALUE);
- read_wait_object_ = NULL;
- if (!read_event_signalled_)
- wait = true;
- DWORD bytes_read_dword = 0;
-
- // Since we cancelled pending IO calls above, we need to know if the
- // read did succeed (i.e. it completed and there's a pending task posted
- // to alert us) or if it was cancelled. This important because if the
- // read completed, we don't want to serialize those bytes again.
- // TODO(jam): for XP, can return TRUE here to wait. also below.
- BOOL rv = GetOverlappedResult(
- handle(), &read_context_.overlapped, &bytes_read_dword,
- wait ? TRUE : FALSE);
- if (rv && read_context_.overlapped.Internal != STATUS_CANCELLED) {
- additional_bytes_read = bytes_read_dword;
- } else if (!rv && (GetLastError() != ERROR_OPERATION_ABORTED)) {
- LOG(ERROR) << "ReleaseHandle got error " << GetLastError() << " when "
- << "checking last read so not returning pipe.";
- got_read_error = true;
- }
- pending_read_ = false;
- }
-
- RawChannel::WriteBuffer* write_buffer = owner_->write_buffer_no_lock();
-
- size_t additional_bytes_written = 0;
- size_t additional_platform_handles_written = 0;
- *write_error = owner_->pending_write_error();
- if (pending_write_) {
- // If we had a pending write, then on XP we just wait till it completes.
- // We use limited size buffers, so Windows should always find paged pool
- // memory to finish the writes.
- // TODO(jam): use background thread to verify that we don't hang here?
- bool wait = is_xp;
- UnregisterWaitEx(write_wait_object_, INVALID_HANDLE_VALUE);
- write_wait_object_ = NULL;
- if (!write_event_signalled_)
- wait = true;
-
- DWORD bytes_written_dword = 0;
-
- // See comment above.
- BOOL rv = GetOverlappedResult(
- handle(), &write_context_.overlapped, &bytes_written_dword,
- wait ? TRUE : FALSE);
- if (rv && write_context_.overlapped.Internal != STATUS_CANCELLED) {
- CHECK(!write_buffer->IsEmpty());
-
- additional_bytes_written = static_cast<size_t>(bytes_written_dword);
- additional_platform_handles_written = platform_handles_written_;
- platform_handles_written_ = 0;
- } else if (!rv && (GetLastError() != ERROR_OPERATION_ABORTED)) {
- LOG(ERROR) << "ReleaseHandle got error " << GetLastError() << " when "
- << "checking last write.";
- *write_error = true;
- }
- pending_write_ = false;
- }
-
- if (got_read_error) {
- return ScopedPlatformHandle();
- }
-
- owner_->SerializeReadBuffer(
- additional_bytes_read, serialized_read_buffer);
- if (!*write_error) {
- owner_->SerializeWriteBuffer(
- additional_bytes_written, additional_platform_handles_written,
- serialized_write_buffer, nullptr);
- }
-
- return ScopedPlatformHandle(handle_.release());
- }
-
- private:
- // Returns true if |owner_| has been reset and there is not pending read or
- // write.
- // Must be called on the I/O thread.
- bool ShouldSelfDestruct() const {
- if (owner_ || suppress_self_destruct_)
- return false;
-
- // Note: Detached, hence no lock needed for |pending_write_|.
- return !pending_read_ && !pending_write_;
- }
-
- // Must be called on the I/O thread. It may be called before or after
- // detaching from the owner.
- void OnReadCompleted(DWORD bytes_read, DWORD error) {
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
- DCHECK(suppress_self_destruct_);
- if (!owner_) {
- pending_read_ = false;
- return;
- }
-
- // Must acquire the read lock before we update pending_read_, since
- // otherwise there is a race condition in ReleaseHandle if this method
- // sets it to false but ReleaseHandle acquired read lock. It would then
- // think there's no pending read and miss the read bytes.
- base::AutoLock locker(owner_->read_lock());
-
- // This can happen if ReleaseHandle was called and it set pending_read to
- // false. We don't want to call owner_->OnReadCompletedNoLock since the
- // read_buffer has been freed.
- if (!pending_read_)
- return;
-
- CHECK(pending_read_);
- pending_read_ = false;
-
- // Note: |OnReadCompleted()| may detach us from |owner_|.
- if (error == ERROR_SUCCESS || error == ERROR_NO_MORE_ITEMS) {
- DCHECK_GT(bytes_read, 0u);
- owner_->OnReadCompletedNoLock(IO_SUCCEEDED, bytes_read);
- } else if (error == ERROR_BROKEN_PIPE || error == STATUS_PIPE_BROKEN) {
- DCHECK_EQ(bytes_read, 0u);
- owner_->OnReadCompletedNoLock(IO_FAILED_SHUTDOWN, 0);
- } else {
- DCHECK_EQ(bytes_read, 0u);
- LOG(WARNING) << "ReadFile: " << logging::SystemErrorCodeToString(error);
- owner_->OnReadCompletedNoLock(IO_FAILED_UNKNOWN, 0);
- }
- }
-
- // Must be called on the I/O thread. It may be called before or after
- // detaching from the owner.
- void OnWriteCompleted(DWORD bytes_written, DWORD error) {
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
- DCHECK(suppress_self_destruct_);
-
- if (!owner_) {
- // No lock needed.
- CHECK(pending_write_);
- pending_write_ = false;
- return;
- }
-
- base::AutoLock locker(owner_->write_lock());
- // This can happen if ReleaseHandle was called and it set pending_write to
- // false. We don't want to call owner_->OnWriteCompletedNoLock since the
- // write_buffer has been freed.
- if (!pending_write_)
- return;
-
- CHECK(pending_write_);
- pending_write_ = false;
-
- // Note: |OnWriteCompleted()| may detach us from |owner_|.
- if (error == ERROR_SUCCESS || error == ERROR_NO_MORE_ITEMS) {
- // Reset |platform_handles_written_| before calling |OnWriteCompleted()|
- // since that function may call back to this class and set it again.
- size_t local_platform_handles_written = platform_handles_written_;
- platform_handles_written_ = 0;
- owner_->OnWriteCompletedNoLock(
- IO_SUCCEEDED, local_platform_handles_written, bytes_written);
- } else if (error == ERROR_BROKEN_PIPE || error == STATUS_PIPE_BROKEN) {
- owner_->OnWriteCompletedNoLock(IO_FAILED_SHUTDOWN, 0, 0);
- } else {
- LOG(WARNING) << "WriteFile: "
- << logging::SystemErrorCodeToString(error);
- owner_->OnWriteCompletedNoLock(IO_FAILED_UNKNOWN, 0, 0);
- }
- }
-
- void OnObjectSignaled(HANDLE object) {
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
- // Since this is called on the IO thread, no locks needed for owner_.
- bool handle_is_valid = false;
- if (owner_)
- owner_->read_lock().Acquire();
- handle_is_valid = handle_.is_valid();
- if (owner_)
- owner_->read_lock().Release();
- if (!handle_is_valid) {
- if (object == read_event_.Get())
- pending_read_ = false;
- else
- pending_write_ = false;
- if (ShouldSelfDestruct())
- delete this;
- return;
- }
-
- // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case
- // they result in a call to |Shutdown()|).
- bool old_suppress_self_destruct = suppress_self_destruct_;
- suppress_self_destruct_ = true;
- if (object == read_event_.Get()) {
- OnReadCompleted(read_context_.overlapped.InternalHigh,
- read_context_.overlapped.Internal);
- } else {
- CHECK(object == write_event_.Get());
- OnWriteCompleted(write_context_.overlapped.InternalHigh,
- write_context_.overlapped.Internal);
- }
-
- // Maybe allow self-destruction again.
- suppress_self_destruct_ = old_suppress_self_destruct;
-
- if (ShouldSelfDestruct())
- delete this;
- }
-
- static void CALLBACK ReadCompleted(void* param, BOOLEAN timed_out) {
- DCHECK(!timed_out);
- // The destructor blocks on any callbacks that are in flight, so we know
- // that that is always a pointer to a valid RawChannelIOHandler.
- RawChannelIOHandler* that = static_cast<RawChannelIOHandler*>(param);
- that->read_event_signalled_ = true;
- that->io_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&RawChannelIOHandler::OnObjectSignaled,
- that->this_weakptr_, that->read_event_.Get()));
- }
-
- static void CALLBACK WriteCompleted(void* param, BOOLEAN timed_out) {
- DCHECK(!timed_out);
- // The destructor blocks on any callbacks that are in flight, so we know
- // that that is always a pointer to a valid RawChannelIOHandler.
- RawChannelIOHandler* that = static_cast<RawChannelIOHandler*>(param);
- that->write_event_signalled_ = true;
- that->io_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&RawChannelIOHandler::OnObjectSignaled,
- that->this_weakptr_, that->write_event_.Get()));
- }
-
- ScopedPlatformHandle handle_;
-
- // We cache this because ReadCompleted and WriteCompleted might get fired
- // after ShutdownIPCSupport is called.
- scoped_refptr<base::TaskRunner> io_task_runner_;
-
- // |owner_| is reset on the I/O thread under |owner_->write_lock()|.
- // Therefore, it may be used on any thread under lock; or on the I/O thread
- // without locking.
- RawChannelWin* owner_;
-
- // The following members must be used on the I/O thread.
- scoped_ptr<ReadBuffer> preserved_read_buffer_after_detach_;
- scoped_ptr<WriteBuffer> preserved_write_buffer_after_detach_;
- bool suppress_self_destruct_;
-
- bool pending_read_;
- base::MessageLoopForIO::IOContext read_context_;
-
- // The following members must be used under |owner_->write_lock()| while the
- // object is still attached to the owner, and only on the I/O thread
- // afterwards.
- bool pending_write_;
- size_t platform_handles_written_;
- base::MessageLoopForIO::IOContext write_context_;
-
- base::win::ScopedHandle read_event_;
- base::win::ScopedHandle write_event_;
-
- HANDLE read_wait_object_;
- HANDLE write_wait_object_;
-
- // Since we use auto-reset event, these variables let ReleaseHandle know if
- // UnregisterWaitEx ended up running a callback or not.
- bool read_event_signalled_;
- bool write_event_signalled_;
-
- // These are used by the callbacks for the wait event watchers.
- base::WeakPtr<RawChannelIOHandler> this_weakptr_;
- base::WeakPtrFactory<RawChannelIOHandler> weak_ptr_factory_;
-
- MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler);
- };
-
- ScopedPlatformHandle ReleaseHandleNoLock(
- std::vector<char>* serialized_read_buffer,
- std::vector<char>* serialized_write_buffer,
- std::vector<int>* serialized_read_fds,
- std::vector<int>* serialized_write_fds,
- bool* write_error) override {
- if (handle_.is_valid()) {
- // SetInitialBuffer could have been called on main thread before OnInit
- // is called on Io thread. and in meantime ReleaseHandle called.
- SerializeReadBuffer(0u, serialized_read_buffer);
-
- // We could have been given messages to write before OnInit.
- SerializeWriteBuffer(0u, 0u, serialized_write_buffer, nullptr);
-
- return handle_.Pass();
- }
-
- return io_handler_->ReleaseHandle(serialized_read_buffer,
- serialized_write_buffer,
- write_error);
- }
-
- bool IsHandleValid() override {
- return GetHandle().is_valid();
- }
-
- IOResult Read(size_t* bytes_read) override {
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
-
- char* buffer = nullptr;
- size_t bytes_to_read = 0;
- read_buffer()->GetBuffer(&buffer, &bytes_to_read);
-
- DCHECK(io_handler_);
- DCHECK(!io_handler_->pending_read());
- BOOL result = ReadFile(
- io_handler_->handle(), buffer, static_cast<DWORD>(bytes_to_read),
- nullptr, &io_handler_->read_context()->overlapped);
- if (!result) {
- DWORD error = GetLastError();
- if (error == ERROR_BROKEN_PIPE)
- return IO_FAILED_SHUTDOWN;
- if (error != ERROR_IO_PENDING) {
- LOG(WARNING) << "ReadFile: " << logging::SystemErrorCodeToString(error);
- return IO_FAILED_UNKNOWN;
- }
- }
-
- // If the read is pending or the read has succeeded but we don't skip
- // completion port on success, instruct |io_handler_| to wait for the
- // completion packet.
- //
- // TODO(yzshen): It seems there isn't document saying that all error cases
- // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion
- // packet. If we do get one for errors, OnObjectSignaled()| will crash so we
- // will learn about it.
- io_handler_->OnPendingReadStarted();
- return IO_PENDING;
- }
-
- IOResult ScheduleRead() override {
- if (!io_handler_)
- return IO_PENDING; // OnInit could have earlied out.
-
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
- DCHECK(io_handler_);
- DCHECK(!io_handler_->pending_read());
-
- size_t bytes_read = 0;
- return Read(&bytes_read);
- }
-
- ScopedPlatformHandleVectorPtr GetReadPlatformHandles(
- size_t num_platform_handles,
- const void* platform_handle_table) override {
- DCHECK_GT(num_platform_handles, 0u);
- ScopedPlatformHandleVectorPtr rv(new PlatformHandleVector());
- rv->resize(num_platform_handles);
-
- const uint64_t* tokens =
- static_cast<const uint64_t*>(platform_handle_table);
- internal::g_broker->TokenToHandle(tokens, num_platform_handles, &rv->at(0));
- return rv.Pass();
- }
-
- size_t SerializePlatformHandles(std::vector<int>* fds) override {
- if (!write_buffer_no_lock()->HavePlatformHandlesToSend())
- return 0u;
-
- PlatformHandle* platform_handles;
- void* serialization_data_temp;
- size_t num_platform_handles;
- write_buffer_no_lock()->GetPlatformHandlesToSend(
- &num_platform_handles, &platform_handles, &serialization_data_temp);
- uint64_t* tokens = static_cast<uint64_t*>(serialization_data_temp);
- DCHECK_GT(num_platform_handles, 0u);
- DCHECK(platform_handles);
-
- internal::g_broker->HandleToToken(
- &platform_handles[0], num_platform_handles, tokens);
- for (size_t i = 0; i < num_platform_handles; i++)
- platform_handles[i] = PlatformHandle();
- return num_platform_handles;
- }
-
- IOResult WriteNoLock(size_t* platform_handles_written,
- size_t* bytes_written) override {
- write_lock().AssertAcquired();
-
- DCHECK(io_handler_);
- DCHECK(!io_handler_->pending_write_no_lock());
-
- size_t num_platform_handles = SerializePlatformHandles(nullptr);
-
- std::vector<WriteBuffer::Buffer> buffers;
- write_buffer_no_lock()->GetBuffers(&buffers);
- DCHECK(!buffers.empty());
-
- // TODO(yzshen): Handle multi-segment writes more efficiently.
- DWORD bytes_written_dword = 0;
-
- BOOL result =
- WriteFile(io_handler_->handle(), buffers[0].addr,
- static_cast<DWORD>(buffers[0].size), &bytes_written_dword,
- &io_handler_->write_context_no_lock()->overlapped);
- if (!result) {
- DWORD error = GetLastError();
- if (error == ERROR_BROKEN_PIPE || error == ERROR_NO_DATA)
- return IO_FAILED_SHUTDOWN;
- if (error != ERROR_IO_PENDING) {
- LOG(WARNING) << "WriteFile: "
- << logging::SystemErrorCodeToString(error);
- return IO_FAILED_UNKNOWN;
- }
- }
-
- // If the write is pending or the write has succeeded but we don't skip
- // completion port on success, instruct |io_handler_| to wait for the
- // completion packet.
- //
- // TODO(yzshen): it seems there isn't document saying that all error cases
- // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion
- // packet. If we do get one for errors, OnObjectSignaled will crash so we
- // will learn about it.
-
- io_handler_->OnPendingWriteStartedNoLock(num_platform_handles);
- return IO_PENDING;
- }
-
- IOResult ScheduleWriteNoLock() override {
- write_lock().AssertAcquired();
-
- DCHECK(io_handler_);
- DCHECK(!io_handler_->pending_write_no_lock());
-
- size_t platform_handles_written = 0;
- size_t bytes_written = 0;
- return WriteNoLock(&platform_handles_written, &bytes_written);
- }
-
- void OnInit() override {
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
-
- if (!handle_.is_valid()) {
- LOG(ERROR) << "Note: RawChannelWin " << this
- << " early exiting in OnInit because no handle";
- return;
- }
-
- DCHECK(handle_.is_valid());
- DCHECK(!io_handler_);
- io_handler_ = new RawChannelIOHandler(this, handle_.Pass());
- }
-
- void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer,
- scoped_ptr<WriteBuffer> write_buffer) override {
- DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
-
- if (!io_handler_) {
- // This is hit when creating a duplicate dispatcher since we don't call
- // Init on it.
- DCHECK(read_buffer->IsEmpty());
- DCHECK(write_buffer->IsEmpty());
- return;
- }
-
- if (io_handler_->pending_read() || io_handler_->pending_write_no_lock()) {
- // |io_handler_| will be alive until pending read/write (if any)
- // completes. Call |CancelIoEx()| or |CancelIo()| so that resources can be
- // freed up as soon as possible.
- // Note: |CancelIo()| only cancels read/write requests started from this
- // thread.
- if (g_vista_or_higher_functions.Get().is_vista_or_higher()) {
- g_vista_or_higher_functions.Get().CancelIoEx(io_handler_->handle(),
- nullptr);
- } else {
- CancelIo(io_handler_->handle());
- }
- }
-
- io_handler_->DetachFromOwnerNoLock(read_buffer.Pass(), write_buffer.Pass());
- io_handler_ = nullptr;
- }
-
- // Passed to |io_handler_| during initialization.
- ScopedPlatformHandle handle_;
-
- RawChannelIOHandler* io_handler_;
-
- MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelWin);
-};
-
-
-} // namespace
-
-// -----------------------------------------------------------------------------
-
-RawChannel* RawChannel::Create(ScopedPlatformHandle handle) {
- return new RawChannelWin(handle.Pass());
-}
-
-size_t RawChannel::GetSerializedPlatformHandleSize() {
- return sizeof(uint64_t);
-}
-
-bool RawChannel::IsOtherEndOf(RawChannel* other) {
- DCHECK_NE(other, this);
- PlatformHandle this_handle = static_cast<RawChannelWin*>(this)->GetHandle();
- PlatformHandle other_handle = static_cast<RawChannelWin*>(other)->GetHandle();
-
- if (g_vista_or_higher_functions.Get().is_vista_or_higher()) {
- WCHAR data1[_MAX_PATH + sizeof(FILE_NAME_INFO)];
- WCHAR data2[_MAX_PATH + sizeof(FILE_NAME_INFO)];
- FILE_NAME_INFO* fileinfo1 = reinterpret_cast<FILE_NAME_INFO *>(data1);
- FILE_NAME_INFO* fileinfo2 = reinterpret_cast<FILE_NAME_INFO *>(data2);
- CHECK(g_vista_or_higher_functions.Get().GetFileInformationByHandleEx(
- this_handle.handle, FileNameInfo, fileinfo1, arraysize(data1)));
- CHECK(g_vista_or_higher_functions.Get().GetFileInformationByHandleEx(
- other_handle.handle, FileNameInfo, fileinfo2, arraysize(data2)));
- std::wstring filepath1(fileinfo1->FileName, fileinfo1->FileNameLength / 2);
- std::wstring filepath2(fileinfo2->FileName, fileinfo2->FileNameLength / 2);
- return filepath1 == filepath2;
- } else {
- // This is to catch developer errors. Let them be caught on Vista and above,
- // i.e. no point in implementing this on XP since support for it will be
- // removed in early 2016.
- return false;
- }
-}
-
-} // namespace edk
-} // namespace mojo
« no previous file with comments | « mojo/edk/system/raw_channel_unittest.cc ('k') | mojo/edk/system/routed_raw_channel.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698