[reSIProcate] Bug in BaseConnection (or TcpBaseTransport?)
Byron Campen
bcampen at estacado.net
Thu May 4 11:06:59 CDT 2006
Huh, this is a behavior I was not aware of. Makes more sense than
the alternative though. Sorry for the false alarm.
Best regards,
Byron Campen
> I’m not sure I understand the virtual destructor case you are making:
>
>
>
> In your example the Connection destructor should get properly
> called right?
>
>
>
> BTW: I found the following text:
>
> Note: if your base class has a virtual destructor, then your
> destructor is automatically virtual. You might need an explicit
> destructor for other reasons, but there's no need to redeclare a
> destructor simply to make sure it is virtual. No matter whether you
> declare it with the virtual keyword, declare it without the virtual
> keyword, or don't declare it at all, it's still virtual.
>
> At: http://www.parashift.com/c++-faq-lite/virtual-
> functions.html#faq-20.7
>
>
>
> Scott
>
>
>
> From: Byron Campen [mailto:bcampen at estacado.net]
> Sent: Thursday, May 04, 2006 10:23 AM
> To: Scott Godin
> Cc: resiprocate-devel
> Subject: Re: [reSIProcate] Bug in BaseConnection (or
> TcpBaseTransport?)
>
>
>
> Scott:
>
> Yes, but all destructors in a class tree need to be
> virtual, or you run into problems. For instance, if you have a
> TcpConnection* cast as a Connection*, and you delete it,
> ~TcpConnection() never gets called, since the vptr doesn't exist.
>
>
>
> list:
>
> I would argue that this self-deletion behavior is
> incorrect, and needs to be removed. Having "delete this" as a side-
> effect of a call is usually insane, and makes a class unsuitable
> for stack allocation. (I am planning on making a sweep through the
> codebase for other instances of "delete this", and bringing poorly-
> chosen instances to the attention to the list) Also, this sort of
> decision should not be made way down at the base-class; this should
> be up to the Transport objects.
>
>
>
> Best regards,
>
> Byron Campen
>
>
>
>
> I suspect what is causing the trap is the DebugLog of
> *currConnection after it has been deleted – we could either remove
> this log, or to get rid of the self deletion… Perhaps we should
> change preparseNewBytes to return an error (or set to a newly
> created error state) – then in Connection::read(), if
> preparseNewBytes returns an error – we should return bytesRead < 0
> – which will cause TcpBaseTransport to delete the connection.
>
>
>
> As for the destructor problem – you are correct – default
> destructors are not virtual. But TlsConnection is not inherited
> from TcpConnection – it is derived from Connection – which does
> have a virtual destructor.
>
>
>
> Scott
>
>
>
> From: resiprocate-devel-bounces at list.sipfoundry.org
> [mailto:resiprocate-devel-bounces at list.sipfoundry.org] On Behalf Of
> Byron Campen
> Sent: Wednesday, May 03, 2006 2:38 PM
> To: resiprocate-devel
> Subject: [reSIProcate] Bug in BaseConnection (or TcpBaseTransport?)
>
>
>
> Here is the relevant code in TcpBaseTransport...
>
>
>
> *snip*
>
>
>
> Connection* currConnection = mConnectionManager.getNextRead(fdset);
>
> if (currConnection)
>
> {
>
> if ( fdset.readyToRead(currConnection->getSocket()) ||
>
> currConnection->hasDataToRead() )
>
> {
>
> DebugLog (<< "TcpBaseTransport::processSomeReads() " <<
> *currConnection);
>
> fdset.clear(currConnection->getSocket());
>
>
>
> int bytesRead = currConnection->read(mStateMachineFifo);
>
> DebugLog (<< "TcpBaseTransport::processSomeReads() "
>
> << *currConnection << " read=" << bytesRead);
>
> if (bytesRead < 0)
>
> {
>
> DebugLog (<< "Closing connection bytesRead=" <<
> bytesRead);
>
> delete currConnection;
>
> }
>
> }
>
>
>
> *snip*
>
>
>
> The problem here is that Connection::read() can result in deletion
> of currConnection (see the following)
>
>
>
> from Connection::read()
>
> *snip*
>
> int
>
> Connection::read(Fifo<TransactionMessage>& fifo)
>
> {
>
> std::pair<char*, size_t> writePair = getWriteBuffer();
>
> size_t bytesToRead = resipMin(writePair.second,
>
> static_cast<size_t>
> (Connection::ChunkSize));
>
>
>
> assert(bytesToRead > 0);
>
> int bytesRead = read(writePair.first, bytesToRead);
>
> if (bytesRead <= 0)
>
> {
>
> delete [] writePair.first;
>
> return bytesRead;
>
> }
>
> getConnectionManager().touch(this);
>
> preparseNewBytes(bytesRead, fifo); //.dcm. may delete this
>
> return bytesRead;
>
> }
>
>
>
> *snip*
>
>
>
> from ConnectionBase::preparseNewBytes()
>
> *snip*
>
> case ReadingHeaders:
>
> {
>
> unsigned int chunkLength = mBufferPos + bytesRead;
>
> char *unprocessedCharPtr;
>
> MsgHeaderScanner::ScanChunkResult scanChunkResult =
>
> mMsgHeaderScanner.scanChunk(mBuffer,
>
> chunkLength,
>
> &unprocessedCharPtr);
>
> if (scanChunkResult == MsgHeaderScanner::scrError)
>
> {
>
> //.jacob. Not a terribly informative warning.
>
> WarningLog(<< "Discarding preparse!");
>
> delete [] mBuffer;
>
> mBuffer = 0;
>
> delete mMessage;
>
> mMessage = 0;
>
> //.jacob. Shouldn't the state also be set here?
>
> delete this;
>
> return;
>
> }
>
>
>
> *snip*
>
>
>
> Long story short, someone throws garbage at us over a Tcp
> socket, and we corrupt our heap. So, where should the
> responsibility for deletion of connections lie? If it belongs in
> ConnectionBase, we need to document this in the header file, in
> upper case, preferably about 50 times. (Although it looks like the
> function return cannot be used to discover whether or not deletion
> occurred, and it appears that this would be difficult to change, so
> I would argue we need to stop this behavior.) And, as a general
> principle, I get very angry when my objects delete themselves on a
> whim. Imagine the fun if I had a stack-allocated Connection that
> decided to delete itself?
>
>
>
> Also, it is worth noting that a virtual destructor has
> not been declared for TcpConnection, and an explicitly non-virtual
> destructor has been declared for TlsConnection. I am not sure
> whether auto-generated destructors are virtual, so there are
> potentially two more guns aimed at our foot here.
>
>
>
> Best regards,
>
> Byron Campen
>
>
>
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://list.resiprocate.org/pipermail/resiprocate-devel/attachments/20060504/84ff2126/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2369 bytes
Desc: not available
URL: <http://list.resiprocate.org/pipermail/resiprocate-devel/attachments/20060504/84ff2126/attachment.bin>
More information about the resiprocate-devel
mailing list