hi ross, colleague could not subscribe to the mailing list with his email address so see below for the forwarded question.
best regards, gerald ------------------------------------------------------------ ---------------------------------------------------- Hi, three weeks ago we've started using libAsan on gcc 4.9 and we have fixed a dozen of small memory errors on our code ever since. Today I'm having an error in the live555 code that came up using libAsan. It seems that the taskscheduler fires up the destructor of SocketDescriptor after an evaluation of true on the fDeleteMyselfNext flag which is set implicitly by calling Medium::close(our_session). The problem is that this event can be fired after the destruction of SocketDescriptor's rtpInterface, meaning that the global variable "rtpInterface" inside SocketDescriptor points to a free'd address. It appears that in our code this has never caused any troubles but now that we use libAsan it has come to our attention since Asan fire a segfault when memory corruption occurs, there are no false positives when using libAsan. An example of the output when printing a line in RTPInterface::removeStreamSocket and in ~RTPInterface: ... Debug: removeStreamSocket @ 0xad3056c8 Debug: delete RTPInterface 0xad3056c8 Debug: removeStreamSocket @ 0xad3056c8 ... As can be seen, after the RTPInterface was delete, removeStreamSocket is being called on the same rtpInterface ptr. As it happens the code inside removeStreamSocket using the invalid ptr doesn't do anything wrong on our side, the first variable being tested is always NULL, a null check prevents that the code continues, this however is purely a coincidence. I've modified ~SocketDescriptor for debugging, lookupRTPInterface(fStreamChannelId) yields 0x0 so that's another way of telling that something is wrong (see code below). Can someone put the same debug prints in their live555 implementation so that it can be confirmed that there is a issue? Regards, Frederik SocketDescriptor::~SocketDescriptor() { fEnv.taskScheduler().turnOffBackgroundReadHandling(fOurSocketNum); removeSocketDescription(fEnv, fOurSocketNum); if (fSubChannelHashTable != NULL) { // Remove knowledge of this socket from any "RTPInterface"s that are using it: HashTable::Iterator* iter = HashTable::Iterator::create(*f SubChannelHashTable); RTPInterface* rtpInterface; char const* key; while ((rtpInterface = (RTPInterface*)(iter->next(key))) != NULL) { u_int64_t streamChannelIdLong = (u_int64_t)key; unsigned char streamChannelId = (unsigned char)streamChannelIdLong; auto i = lookupRTPInterface(fStreamChannelId); if (i == rtpInterface) { rtpInterface->removeStreamSocket(fOurSocketNum, streamChannelId); } else { qDebug() << "lookupRTPInterface(fStreamChannelId) (" << i << ") != rtpInterface (" << rtpInterface << ") @ SocketDescriptor " << this; // prevent further errors: fServerRequestAlternativeByteHandler = nullptr; } } delete iter; // Then remove the hash table entries themselves, and then remove the hash table: while (fSubChannelHashTable->RemoveNext() != NULL) {} delete fSubChannelHashTable; } // Finally: if (fServerRequestAlternativeByteHandler != NULL) { // Hack: Pass a special character to our alternative byte handler, to tell it that either // - an error occurred when reading the TCP socket, or // - no error occurred, but it needs to take over control of the TCP socket once again. u_int8_t specialChar = fReadErrorOccurred ? 0xFF : 0xFE; (*fServerRequestAlternativeByteHandler)(fServerRequestAlternativeByteHandlerClientData, specialChar); } }
_______________________________________________ live-devel mailing list live-devel@lists.live555.com http://lists.live555.com/mailman/listinfo/live-devel