]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Enforce more "safe job callbacks" invariants, albeit at runtime
authorAlex Rousskov <rousskov@measurement-factory.com>
Fri, 16 Jul 2021 17:15:49 +0000 (13:15 -0400)
committerAlex Rousskov <rousskov@measurement-factory.com>
Fri, 16 Jul 2021 17:33:09 +0000 (13:33 -0400)
src/base/AsyncJob.cc
src/base/AsyncJob.h

index bf924eb4b1da3a08c6edb17705a89fa69f23e6ba..16d444e01792a6983b4d5403b3c6a5812e06506f 100644 (file)
@@ -24,6 +24,7 @@ AsyncJob::Pointer AsyncJob::Start(AsyncJob *j)
 {
     AsyncJob::Pointer job(j);
     CallJobHere(93, 5, job, AsyncJob, start);
+    job->started_ = true; // it is the attempt that counts
     return job;
 }
 
@@ -38,6 +39,7 @@ AsyncJob::~AsyncJob()
 {
     debugs(93,5, "AsyncJob destructed, this=" << this <<
            " type=" << typeName << " [" << id << ']');
+    assert(!started_ || swanSang_);
 }
 
 void AsyncJob::start()
@@ -141,9 +143,16 @@ void AsyncJob::callEnd()
         AsyncCall::Pointer inCallSaved = inCall;
         void *thisSaved = this;
 
+        // TODO: Swallow swanSong() exceptions to reduce memory leaks.
+
+        // Job callback invariant: swanSong() is (only) called for started jobs.
+        // Here to detect violations in kids that forgot to call our swanSong().
+        assert(started_);
+
+        swanSang_ = true; // it is the attempt that counts
         swanSong();
 
-        delete this; // this is the only place where the object is deleted
+        delete this; // this is the only place where a started job is deleted
 
         // careful: this object does not exist any more
         debugs(93, 6, HERE << *inCallSaved << " ended " << thisSaved);
index db17297f3d7616e7a69b5678406e08c7c753fbb9..fe3e26d74fc57a96132413a74f296ced3285101c 100644 (file)
@@ -74,6 +74,9 @@ protected:
     const char *stopReason; ///< reason for forcing done() to be true
     const char *typeName; ///< kid (leaf) class name, for debugging
     AsyncCall::Pointer inCall; ///< the asynchronous call being handled, if any
+
+    bool started_ = false; ///< Start() has finished successfully
+    bool swanSang_ = false; ///< swanSong() was called
 };
 
 #endif /* SQUID_ASYNC_JOB_H */