#include <windows.h>
-#include "base/basictypes.h"
+#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/lock.h"
class RawChannelWin : public RawChannel {
public:
- RawChannelWin(embedder::ScopedPlatformHandle handle,
- Delegate* delegate,
- base::MessageLoopForIO* message_loop);
+ RawChannelWin(embedder::ScopedPlatformHandle handle);
virtual ~RawChannelWin();
+ // |RawChannel| public methods:
+ virtual size_t GetSerializedPlatformHandleSize() const OVERRIDE;
+
private:
// RawChannelIOHandler receives OS notifications for I/O completion. It must
// be created on the I/O thread.
// Must be called on the I/O thread.
bool ShouldSelfDestruct() const;
- // Must be called on the I/O thread. It could be called before or after
- // detached from the owner.
+ // 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);
- // Must be called on the I/O thread. It could be called before or after
- // detached from the owner.
+ // 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);
embedder::ScopedPlatformHandle handle_;
// 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_;
DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler);
};
- // |RawChannel| implementation:
+ // |RawChannel| private methods:
virtual IOResult Read(size_t* bytes_read) OVERRIDE;
virtual IOResult ScheduleRead() OVERRIDE;
- virtual IOResult WriteNoLock(size_t* bytes_written) OVERRIDE;
+ virtual IOResult WriteNoLock(size_t* platform_handles_written,
+ size_t* bytes_written) OVERRIDE;
virtual IOResult ScheduleWriteNoLock() OVERRIDE;
virtual bool OnInit() OVERRIDE;
virtual void OnShutdownNoLock(
RawChannelWin* owner,
embedder::ScopedPlatformHandle handle) : handle_(handle.Pass()),
owner_(owner),
+ suppress_self_destruct_(false),
pending_read_(false),
pending_write_(false) {
memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped));
DCHECK(!owner_ ||
base::MessageLoop::current() == owner_->message_loop_for_io());
- if (context == &read_context_)
- OnReadCompleted(bytes_transferred, error);
- else if (context == &write_context_)
- OnWriteCompleted(bytes_transferred, error);
- else
- NOTREACHED();
+ {
+ // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they
+ // result in a call to |Shutdown()|).
+ base::AutoReset<bool> resetter(&suppress_self_destruct_, true);
+
+ if (context == &read_context_)
+ OnReadCompleted(bytes_transferred, error);
+ else if (context == &write_context_)
+ OnWriteCompleted(bytes_transferred, error);
+ else
+ NOTREACHED();
+ }
if (ShouldSelfDestruct())
delete this;
}
bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const {
- if (owner_)
+ if (owner_ || suppress_self_destruct_)
return false;
// Note: Detached, hence no lock needed for |pending_write_|.
DWORD error) {
DCHECK(!owner_ ||
base::MessageLoop::current() == owner_->message_loop_for_io());
+ DCHECK(suppress_self_destruct_);
CHECK(pending_read_);
pending_read_ = false;
if (error != ERROR_SUCCESS) {
DCHECK_EQ(bytes_read, 0u);
- PLOG_IF(ERROR, error != ERROR_BROKEN_PIPE) << "ReadFile";
+ LOG_IF(ERROR, error != ERROR_BROKEN_PIPE)
+ << "ReadFile: " << logging::SystemErrorCodeToString(error);
owner_->OnReadCompleted(false, 0);
} else {
DCHECK_GT(bytes_read, 0u);
DWORD error) {
DCHECK(!owner_ ||
base::MessageLoop::current() == owner_->message_loop_for_io());
+ DCHECK(suppress_self_destruct_);
if (!owner_) {
// No lock needed.
}
if (error != ERROR_SUCCESS) {
- LOG(ERROR) << "WriteFile failed: " << error;
- owner_->OnWriteCompleted(false, 0);
+ LOG(ERROR) << "WriteFile: " << logging::SystemErrorCodeToString(error);
+ owner_->OnWriteCompleted(false, 0, 0);
} else {
- owner_->OnWriteCompleted(true, bytes_written);
+ owner_->OnWriteCompleted(true, 0, bytes_written);
}
}
-RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle,
- Delegate* delegate,
- base::MessageLoopForIO* message_loop)
- : RawChannel(delegate, message_loop),
- handle_(handle.Pass()),
+RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle)
+ : handle_(handle.Pass()),
io_handler_(NULL),
skip_completion_port_on_success_(
g_vista_or_higher_functions.Get().is_vista_or_higher()) {
DCHECK(!io_handler_);
}
+size_t RawChannelWin::GetSerializedPlatformHandleSize() const {
+ // TODO(vtl): Implement.
+ return 0;
+}
+
RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) {
DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
DCHECK(io_handler_);
DCHECK_EQ(bytes_read_dword, 0u);
DWORD error = GetLastError();
if (error != ERROR_IO_PENDING) {
- LOG_IF(ERROR, error != ERROR_BROKEN_PIPE) << "ReadFile failed: " << error;
+ LOG_IF(ERROR, error != ERROR_BROKEN_PIPE)
+ << "ReadFile: " << logging::SystemErrorCodeToString(error);
return IO_FAILED;
}
}
return io_result;
}
-RawChannel::IOResult RawChannelWin::WriteNoLock(size_t* bytes_written) {
+RawChannel::IOResult RawChannelWin::WriteNoLock(
+ size_t* platform_handles_written,
+ size_t* bytes_written) {
write_lock().AssertAcquired();
DCHECK(io_handler_);
DCHECK(!io_handler_->pending_write_no_lock());
+ if (write_buffer_no_lock()->HavePlatformHandlesToSend()) {
+ // TODO(vtl): Implement.
+ NOTIMPLEMENTED();
+ }
+
std::vector<WriteBuffer::Buffer> buffers;
write_buffer_no_lock()->GetBuffers(&buffers);
DCHECK(!buffers.empty());
}
if (result && skip_completion_port_on_success_) {
+ *platform_handles_written = 0;
*bytes_written = bytes_written_dword;
return IO_SUCCEEDED;
}
DCHECK(io_handler_);
DCHECK(!io_handler_->pending_write_no_lock());
+ // TODO(vtl): Do something with |platform_handles_written|.
+ size_t platform_handles_written = 0;
size_t bytes_written = 0;
- IOResult io_result = WriteNoLock(&bytes_written);
+ IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written);
if (io_result == IO_SUCCEEDED) {
DCHECK(skip_completion_port_on_success_);
// Static factory method declared in raw_channel.h.
// static
-RawChannel* RawChannel::Create(embedder::ScopedPlatformHandle handle,
- Delegate* delegate,
- base::MessageLoopForIO* message_loop) {
- return new RawChannelWin(handle.Pass(), delegate, message_loop);
+scoped_ptr<RawChannel> RawChannel::Create(
+ embedder::ScopedPlatformHandle handle) {
+ return scoped_ptr<RawChannel>(new RawChannelWin(handle.Pass()));
}
} // namespace system