浏览代码

Fix bug with permanent callbacks that delete themselves when run. Patch from Evan Jones.

kenton@google.com 15 年之前
父节点
当前提交
eeb8fd7dc8
共有 3 个文件被更改,包括 25 次插入6 次删除
  1. 1 0
      CONTRIBUTORS.txt
  2. 12 6
      src/google/protobuf/stubs/common.h
  3. 12 0
      src/google/protobuf/stubs/common_unittest.cc

+ 1 - 0
CONTRIBUTORS.txt

@@ -83,5 +83,6 @@ Patch contributors:
     * Optimize Java serialization of strings so that UTF-8 encoding happens only
       once per string per serialization call.
     * Clean up some Java warnings.
+    * Fix bug with permanent callbacks that delete themselves when run.
   Michael Kucharski <m.kucharski@gmail.com>
     * Added CodedInputStream.getTotalBytesRead().

+ 12 - 6
src/google/protobuf/stubs/common.h

@@ -843,8 +843,9 @@ class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure {
   ~FunctionClosure0();
 
   void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
     function_();
-    if (self_deleting_) delete this;
+    if (needs_delete) delete this;
   }
 
  private:
@@ -862,8 +863,9 @@ class MethodClosure0 : public Closure {
   ~MethodClosure0() {}
 
   void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
     (object_->*method_)();
-    if (self_deleting_) delete this;
+    if (needs_delete) delete this;
   }
 
  private:
@@ -884,8 +886,9 @@ class FunctionClosure1 : public Closure {
   ~FunctionClosure1() {}
 
   void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
     function_(arg1_);
-    if (self_deleting_) delete this;
+    if (needs_delete) delete this;
   }
 
  private:
@@ -906,8 +909,9 @@ class MethodClosure1 : public Closure {
   ~MethodClosure1() {}
 
   void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
     (object_->*method_)(arg1_);
-    if (self_deleting_) delete this;
+    if (needs_delete) delete this;
   }
 
  private:
@@ -929,8 +933,9 @@ class FunctionClosure2 : public Closure {
   ~FunctionClosure2() {}
 
   void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
     function_(arg1_, arg2_);
-    if (self_deleting_) delete this;
+    if (needs_delete) delete this;
   }
 
  private:
@@ -952,8 +957,9 @@ class MethodClosure2 : public Closure {
   ~MethodClosure2() {}
 
   void Run() {
+    bool needs_delete = self_deleting_;  // read in case callback deletes
     (object_->*method_)(arg1_, arg2_);
-    if (self_deleting_) delete this;
+    if (needs_delete) delete this;
   }
 
  private:

+ 12 - 0
src/google/protobuf/stubs/common_unittest.cc

@@ -182,11 +182,17 @@ class ClosureTest : public testing::Test {
     a_ = 0;
     b_ = NULL;
     c_.clear();
+    permanent_closure_ = NULL;
+  }
+
+  void DeleteClosureInCallback() {
+    delete permanent_closure_;
   }
 
   int a_;
   const char* b_;
   string c_;
+  Closure* permanent_closure_;
 
   static ClosureTest* current_instance_;
 };
@@ -340,6 +346,12 @@ TEST_F(ClosureTest, TestPermanentClosureMethod2) {
   delete closure;
 }
 
+TEST_F(ClosureTest, TestPermanentClosureDeleteInCallback) {
+  permanent_closure_ = NewPermanentCallback((ClosureTest*) this,
+      &ClosureTest::DeleteClosureInCallback);
+  permanent_closure_->Run();
+}
+
 }  // anonymous namespace
 }  // namespace protobuf
 }  // namespace google