On 01/07/2014 08:35 AM, Alex Rousskov wrote:

> 2) [Add cbdata debugging to] find which object stores the invalid cbdata
> pointer. Then find how that invalid pointer gets to that object. 

I think it happens here:


>> #8  0x0834f190 in CommCbMemFunT (aMeth=
>>     (void (Comm::TcpReceiver::*)(Comm::TcpReceiver * const, const
>> CommCbMemFunT<Comm::TcpReceiver, CommCloseCbParams>::Params &))
>> 0x834e270 <Comm::TcpReceiver::tcpConnectionClosed(CommCloseCbParams
>> const&)>, aJob=..., this=0xbffff268) at ../../../src/CommCalls.h:180


where we are passing a raw job pointer (job.get()) to CommCloseCbParams
object which then uses it as cbdata in CommCommonCbParams constructor:

>     CommCbMemFunT(const CbcPointer<C> &job, Method meth): JobDialer<C>(job),
>             CommDialerParamsT<Params_>(job.get()),

>     CommCloseCbParams(void *aData);

> CommCommonCbParams::CommCommonCbParams(void *aData):
>         data(cbdataReference(aData)), ...


Does the attached untested patch help?


FWIW, you may also use the attached test program as a simple test case.
It has the same class hierarchy as yours and illustrates how while
individual objects have different "this" pointers, they all have the
same (and correct) toCbdata() pointer, regardless of the inheritance order:

  BC:            TrueCbdata=0xbfb306f8
   A=0xbfb3070c   A::cbdata=0xbfb306f8 OK
   B=0xbfb306f8   B::cbdata=0xbfb306f8 OK
   C=0xbfb30700   C::cbdata=0xbfb306f8 OK
  BC=0xbfb306f8  BC::cbdata=0xbfb306f8 OK

  CB:            TrueCbdata=0xbfb30714
   A=0xbfb30728   A::cbdata=0xbfb30714 OK
   B=0xbfb3071c   B::cbdata=0xbfb30714 OK
   C=0xbfb30714   C::cbdata=0xbfb30714 OK
  CB=0xbfb30714  CB::cbdata=0xbfb30714 OK


The buggy code in Squid was using a raw job pointer from the left column
instead of using toCbdata() pointer from the right column.
Unfortunately, due to cbdata being passed and stored as void*, the
compiler cannot catch such bugs. There may be more of these.


HTH,

Alex.

Comm job callbacks need job's cbdata pointer, not a job pointer.

Otherwise, in complex inheritance hierarchies, some [inner] classes will
hit cbdata cookie assertions when scheduling Comm calls with callbacks.

=== modified file 'src/CommCalls.h'
--- src/CommCalls.h	2013-10-25 00:13:46 +0000
+++ src/CommCalls.h	2014-01-14 02:12:00 +0000
@@ -159,41 +159,41 @@ public:
 // Get comm params of an async comm call
 template <class Params>
 Params &GetCommParams(AsyncCall::Pointer &call)
 {
     typedef CommDialerParamsT<Params> DialerParams;
     DialerParams *dp = dynamic_cast<DialerParams*>(call->getDialer());
     assert(dp);
     return dp->params;
 }
 
 // All job dialers with comm parameters are merged into one since they
 // all have exactly one callback argument and differ in Params type only
 template <class C, class Params_>
 class CommCbMemFunT: public JobDialer<C>, public CommDialerParamsT<Params_>
 {
 public:
     typedef Params_ Params;
     typedef void (C::*Method)(const Params &io);
 
     CommCbMemFunT(const CbcPointer<C> &aJob, Method aMeth): JobDialer<C>(aJob),
-            CommDialerParamsT<Params_>(aJob.get()),
+            CommDialerParamsT<Params_>(aJob->toCbdata()),
             method(aMeth) {}
 
     virtual bool canDial(AsyncCall &c) {
         return JobDialer<C>::canDial(c) &&
                this->params.syncWithComm();
     }
 
     virtual void print(std::ostream &os) const {
         os << '(';
         this->params.print(os);
         os << ')';
     }
 
 public:
     Method method;
 
 protected:
     virtual void doDial() { ((&(*this->job))->*method)(this->params); }
 };
 

Reply via email to