diff options
author | avallee <avallee@chromium.org> | 2015-09-10 12:38:27 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-10 19:39:01 +0000 |
commit | 0266f40e73c10c35d47f7f7784a6e0599065593a (patch) | |
tree | 2d53bc8bc44accbcf3ef11abdf30702d7202ab70 /native_client_sdk/src | |
parent | 546b6d6881183ef83cc85048285ec29c839489bf (diff) | |
download | chromium_src-0266f40e73c10c35d47f7f7784a6e0599065593a.zip chromium_src-0266f40e73c10c35d47f7f7784a6e0599065593a.tar.gz chromium_src-0266f40e73c10c35d47f7f7784a6e0599065593a.tar.bz2 |
NACL_IO: Split handle locks.
Under linux it is possile for a single fd to allow Thread A to block on
reading from a fd while Thread B writes to the same fd.
Read-like operations now use an input_lock_. Write-like operations under
an output_lock_. Handle and attributes remain on the handle_lock_.
Added the inverse of AUTO_LOCK; AUTO_UNLOCK which unlocks until end of
scope and then re-locks.
See
https://android.googlesource.com/platform/system/core/+/master/adb/transport.cpp
for an example use, specifically, the read and write threads use the
same t->fd.
BUG=516764
Review URL: https://codereview.chromium.org/1321883003
Cr-Commit-Position: refs/heads/master@{#348214}
Diffstat (limited to 'native_client_sdk/src')
4 files changed, 30 insertions, 6 deletions
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc b/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc index 4f88bbf..c3fb86f 100644 --- a/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc +++ b/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc @@ -65,6 +65,9 @@ Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) { off_t node_size; AUTO_LOCK(handle_lock_); + if (!node_->IsSeekable()) + return ESPIPE; + Error error = node_->GetSize(&node_size); if (error) return error; @@ -101,9 +104,14 @@ Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) { } Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) { - AUTO_LOCK(handle_lock_); + sdk_util::AutoLock read_lock(handle_lock_); if (OpenMode() == O_WRONLY) return EACCES; + if (!node_->IsSeekable()){ + read_lock.Unlock(); + AUTO_LOCK(input_lock_); + return node_->Read(handle_attr_, buf, nbytes, cnt); + } Error error = node_->Read(handle_attr_, buf, nbytes, cnt); if (0 == error) handle_attr_.offs += *cnt; @@ -111,9 +119,14 @@ Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) { } Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) { - AUTO_LOCK(handle_lock_); + sdk_util::AutoLock write_lock(handle_lock_); if (OpenMode() == O_RDONLY) return EACCES; + if (!node_->IsSeekable()){ + write_lock.Unlock(); + AUTO_LOCK(output_lock_); + return node_->Write(handle_attr_, buf, nbytes, cnt); + } Error error = node_->Write(handle_attr_, buf, nbytes, cnt); if (0 == error) handle_attr_.offs += *cnt; @@ -139,6 +152,9 @@ Error KernelHandle::Fcntl(int request, int* result, ...) { Error KernelHandle::VFcntl(int request, int* result, va_list args) { switch (request) { case F_GETFL: { + // Should not block, but could if blocked on Connect or Accept. This is + // acceptable. + AUTO_LOCK(handle_lock_); *result = handle_attr_.flags; return 0; } @@ -190,7 +206,7 @@ Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) { if (OpenMode() == O_WRONLY) return EACCES; - AUTO_LOCK(handle_lock_); + AUTO_LOCK(input_lock_); return sock->Recv(handle_attr_, buf, len, flags, out_len); } @@ -206,7 +222,7 @@ Error KernelHandle::RecvFrom(void* buf, if (OpenMode() == O_WRONLY) return EACCES; - AUTO_LOCK(handle_lock_); + AUTO_LOCK(input_lock_); return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen, out_len); } @@ -218,7 +234,7 @@ Error KernelHandle::Send(const void* buf, size_t len, int flags, int* out_len) { if (OpenMode() == O_RDONLY) return EACCES; - AUTO_LOCK(handle_lock_); + AUTO_LOCK(output_lock_); return sock->Send(handle_attr_, buf, len, flags, out_len); } @@ -234,7 +250,7 @@ Error KernelHandle::SendTo(const void* buf, if (OpenMode() == O_RDONLY) return EACCES; - AUTO_LOCK(handle_lock_); + AUTO_LOCK(output_lock_); return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen, out_len); } diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_handle.h b/native_client_sdk/src/libraries/nacl_io/kernel_handle.h index e586c5d..54f455f 100644 --- a/native_client_sdk/src/libraries/nacl_io/kernel_handle.h +++ b/native_client_sdk/src/libraries/nacl_io/kernel_handle.h @@ -84,6 +84,9 @@ class KernelHandle : public sdk_util::RefObject { ScopedFilesystem filesystem_; ScopedNode node_; + sdk_util::SimpleLock input_lock_; + sdk_util::SimpleLock output_lock_; + // Protects the handle and attributes. sdk_util::SimpleLock handle_lock_; HandleAttr handle_attr_; diff --git a/native_client_sdk/src/libraries/nacl_io/node.cc b/native_client_sdk/src/libraries/nacl_io/node.cc index 0c307a5..6ca1a20 100644 --- a/native_client_sdk/src/libraries/nacl_io/node.cc +++ b/native_client_sdk/src/libraries/nacl_io/node.cc @@ -226,6 +226,10 @@ bool Node::IsaSock() { return GetType() == S_IFSOCK; } +bool Node::IsSeekable() { + return !(IsaSock() || GetType() == S_IFIFO); +} + Error Node::Isatty() { return ENOTTY; } diff --git a/native_client_sdk/src/libraries/nacl_io/node.h b/native_client_sdk/src/libraries/nacl_io/node.h index f1ebdc3c..917aee4 100644 --- a/native_client_sdk/src/libraries/nacl_io/node.h +++ b/native_client_sdk/src/libraries/nacl_io/node.h @@ -106,6 +106,7 @@ class Node : public sdk_util::RefObject { virtual bool IsaDir(); virtual bool IsaFile(); virtual bool IsaSock(); + virtual bool IsSeekable(); // Number of children for this node (directory) virtual int ChildCount(); |