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

Unified Diff: content/child/shared_memory_data_consumer_handle.cc

Issue 1186053004: Cancel loading when body stream reader is detached. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@error-ipc-data-consumer
Patch Set: Created 5 years, 6 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
Index: content/child/shared_memory_data_consumer_handle.cc
diff --git a/content/child/shared_memory_data_consumer_handle.cc b/content/child/shared_memory_data_consumer_handle.cc
index beb470d96d31e91d05214d1b13b4e1909ae242cc..01f9d5abd5fa072bcfb04bde17ea123054c37453 100644
--- a/content/child/shared_memory_data_consumer_handle.cc
+++ b/content/child/shared_memory_data_consumer_handle.cc
@@ -49,10 +49,13 @@ using Result = blink::WebDataConsumerHandle::Result;
class SharedMemoryDataConsumerHandle::Context final
: public base::RefCountedThreadSafe<Context> {
public:
- Context()
+ explicit Context(const base::Closure& on_clear)
: result_(Ok),
first_offset_(0),
client_(nullptr),
+ writer_task_runner_(base::MessageLoop::current()->task_runner()),
+ on_clear_(on_clear),
+ is_on_clear_valid_(!on_clear_.is_null()),
is_handle_active_(true),
is_two_phase_read_in_progress_(false) {}
@@ -60,6 +63,10 @@ class SharedMemoryDataConsumerHandle::Context final
void ClearIfNecessary() {
if (!is_handle_locked() && !is_handle_active()) {
// No one is interested in the contents.
+ if (is_on_clear_valid_) {
+ // We post a task even in the writer thread in order to keep reentrancy.
hiroshige 2015/06/22 18:23:16 how about adding "because didGetReadable() can des
yhirano 2015/06/23 05:28:37 Done.
+ writer_task_runner_->PostTask(FROM_HERE, on_clear_);
+ }
Clear();
}
}
@@ -105,6 +112,22 @@ class SharedMemoryDataConsumerHandle::Context final
base::Bind(&Context::NotifyInternal, this, false));
}
void Notify() { NotifyInternal(true); }
+ void ResetOnClear() {
+ if (on_clear_.is_null()) {
+ DCHECK(!is_on_clear_valid_);
+ return;
+ }
+ is_on_clear_valid_ = false;
+ if (writer_task_runner_->BelongsToCurrentThread()) {
+ // We can reset the closure immediately.
+ on_clear_.Reset();
+ } else {
+ // We need to reset |on_clear_| on the right thread because it might
+ // lead to the object destruction.
+ writer_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&Context::ResetOnClear, this));
+ }
+ }
bool is_handle_locked() const { return notification_task_runner_; }
bool IsReaderBoundToCurrentThread() const {
return notification_task_runner_ &&
@@ -159,10 +182,15 @@ class SharedMemoryDataConsumerHandle::Context final
queue_.clear();
first_offset_ = 0;
client_ = nullptr;
+ // Note this doesn't work in the destructor if |on_clear_| is not null. We
hiroshige 2015/06/22 18:23:16 This comment might be better to be placed just bef
yhirano 2015/06/23 05:28:37 Done.
+ // have an assert in the destructor.
+ ResetOnClear();
}
friend class base::RefCountedThreadSafe<Context>;
~Context() {
+ DCHECK(on_clear_.is_null());
+
// This is necessary because the queue stores raw pointers.
Clear();
}
@@ -177,6 +205,12 @@ class SharedMemoryDataConsumerHandle::Context final
size_t first_offset_;
Client* client_;
scoped_refptr<base::SingleThreadTaskRunner> notification_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> writer_task_runner_;
+ base::Closure on_clear_;
+ // We need this boolean variable to remember if |on_clear_| is callable
+ // because we need to set |on_clear_| only on the writer thread and hence
hiroshige 2015/06/22 18:23:16 optional: how about "... because |on_clear_| is re
yhirano 2015/06/23 05:28:38 I think it misleading the callback will be reset s
+ // |on_clear_.is_null()| is untrustworthy.
+ bool is_on_clear_valid_;
hiroshige 2015/06/22 18:23:16 Please add a comment that |on_clear_| and |is_on_c
yhirano 2015/06/23 05:28:37 Other variables are also protected by the lock, so
bool is_handle_active_;
bool is_two_phase_read_in_progress_;
@@ -191,6 +225,8 @@ SharedMemoryDataConsumerHandle::Writer::Writer(
SharedMemoryDataConsumerHandle::Writer::~Writer() {
Close();
+ base::AutoLock lock(context_->lock());
+ context_->ResetOnClear();
}
void SharedMemoryDataConsumerHandle::Writer::AddData(
@@ -234,6 +270,7 @@ void SharedMemoryDataConsumerHandle::Writer::Close() {
base::AutoLock lock(context_->lock());
if (context_->result() == Ok) {
context_->set_result(Done);
+ context_->ResetOnClear();
needs_notification = context_->IsEmpty();
}
}
@@ -260,6 +297,7 @@ void SharedMemoryDataConsumerHandle::Writer::Fail() {
context_->ClearQueue();
}
+ context_->ResetOnClear();
needs_notification = true;
}
}
@@ -362,7 +400,14 @@ Result SharedMemoryDataConsumerHandle::ReaderImpl::endRead(size_t read_size) {
SharedMemoryDataConsumerHandle::SharedMemoryDataConsumerHandle(
BackpressureMode mode,
scoped_ptr<Writer>* writer)
- : context_(new Context) {
+ : SharedMemoryDataConsumerHandle(mode, base::Closure(), writer) {
+}
+
+SharedMemoryDataConsumerHandle::SharedMemoryDataConsumerHandle(
+ BackpressureMode mode,
+ const base::Closure& on_clear,
+ scoped_ptr<Writer>* writer)
+ : context_(new Context(on_clear)) {
writer->reset(new Writer(context_, mode));
}

Powered by Google App Engine
This is Rietveld 408576698