From kde-commits Fri Mar 02 20:19:22 2007 From: Andras Mantia Date: Fri, 02 Mar 2007 20:19:22 +0000 To: kde-commits Subject: branches/KDE/3.5/kdewebdev/quanta Message-Id: <1172866762.155775.23246.nullmailer () svn ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=117286683714587 SVN commit 638661 by amantia: Fix crash when the tag editing dialog was quickly invoke after a delete from the tag. Add guard for a possible crash in the rebuild process. Add some code to track the node creation/destruction process to help debugging parser related crashes. M +22 -0 parsers/node.cpp M +69 -55 parsers/parser.cpp M +17 -0 parsers/parsercommon.cpp M +1 -0 parsers/parsercommon.h M +2 -1 parsers/saparser.cpp M +2 -2 quanta.kdevelop M +2 -2 src/quanta.cpp M +8 -2 src/quantaview.cpp --- branches/KDE/3.5/kdewebdev/quanta/parsers/node.cpp #638660:638661 @@ -27,6 +27,8 @@ #include "structtreetag.h" #include "kafkacommon.h" +QValueList nodes; //list of all created nodes. Used to do some own memory management and avoid double deletes, for whatever reason they happen... + int NN = 0; //for debugging purposes: count the Node objects GroupElementMapList globalGroupMap; @@ -46,11 +48,23 @@ m_leafNode = 0L; m_groupElements.clear(); NN++; + if (nodes.contains(this) == 0) + nodes.append(this); + else + { + kdError(24000) << "A node with this address " << this << " already exists!" << endl; + } } Node::~Node() { + if (nodes.contains(this) == 0) + { + kdError(24000) << "No node with this address " << this << " was allocated!" << endl; + return; + } + //It has no use, except to know when it crash why it has crashed. //If it has crashed here, the Node doesn't exist anymore. // If it has crashed the next line, it is a GroupElements bug. @@ -60,6 +74,8 @@ tag->setCleanStrBuilt(false); detachNode(); + if (nodes.contains(this) > 0) + nodes.remove(this); if (prev && prev->next == this) prev->next = 0L; if (parent && parent->child == this) @@ -487,6 +503,12 @@ void Node::detachNode() { + if (nodes.contains(this) == 0) + { + kdError(24000) << "No node with this address " << this << " was allocated!" << endl; + return; + } + int count = 0; //kdDebug(24000) << &m_groupElements << " " << this << endl; //Remove the references to this node from the list of group elements. --- branches/KDE/3.5/kdewebdev/quanta/parsers/parser.cpp #638660:638661 @@ -68,6 +68,7 @@ static const QChar space(' '); extern int NN; +extern QValueList nodes; Parser::Parser() { @@ -520,12 +521,16 @@ // clearGroups(); if (baseNode) { - kdDebug(24000) << "NN before delete = " << NN << endl; + kdDebug(24000) << "Node objects before delete = " << NN << " ; list count = " << nodes.count() << endl; //kdDebug(24000) << "baseNode before delete = " << baseNode << endl; //ParserCommon::coutTree(m_node, 2); delete baseNode; baseNode = 0L; - kdDebug(24000) << "NN after delete = " << NN << endl; + kdDebug(24000) << "Node objects after delete = " << NN << " ; list count = " << nodes.count() << endl; + QValueList nList = nodes; +/* for (QValueList::ConstIterator it = nList.constBegin(); it != nList.constEnd(); ++it) + delete (*it); + kdDebug(24000) << "Node objects after cleanup = " << NN << " ; list count = " << nodes.count() << endl; */ } m_node = 0L; @@ -1013,9 +1018,10 @@ kdDebug(24000) << QString("Invalid area: %1,%2,%3,%4").arg(area.bLine).arg(area.bCol).arg(area.eLine).arg(area.eCol) << "\n"; +// kdDebug(24000) << "lastNode1: " << lastNode << " " << lastNode->tag << endl; deleteNodes(firstNode->nextSibling(), lastNode, modifs); +// kdDebug(24000) << "lastNode2: " << lastNode << " " << lastNode->tag << endl; - firstNode->child = 0L; Node *lastInserted = 0L; //this makes sure that the first found node it put right after the firstNode @@ -1053,10 +1059,11 @@ m_saParser->setParsingEnabled(saParserEnabled); return parse(w); } - +// kdDebug(24000) << "lastNode3: " << lastNode << " " << lastNode->tag << endl; bool goUp; if (lastNode && lastInserted) { +// kdDebug(24000) << "lastNode4: " << lastNode << " " << lastNode->tag << endl; //merge the nodes if they are both of type Text or Empty if ( (lastInserted->tag->type == Tag::Empty || lastInserted->tag->type == Tag::Text) && (lastNode->tag->type == Tag::Empty || lastNode->tag->type == Tag::Text)) @@ -1115,9 +1122,11 @@ node = lastInserted; +// kdDebug(24000) << "lastNode5: " << lastNode << " " << lastNode->tag << endl; QTag *qTag = 0L; while (node && lastNode) { +// kdDebug(24000) << "lastNode6: " << lastNode << " " << lastNode->tag << endl; qTag = 0L; goUp = ( node->parent && ( (lastNode->tag->type == Tag::XmlTagEnd && QuantaCommon::closesTag(node->parent->tag, lastNode->tag) ) || @@ -1142,65 +1151,69 @@ (!m_dtd->caseSensitive && node->tag->name.lower() == node->parent->tag->name.lower())) ) goUp = false; //it can happen that the tag closes the previous and not the parent - if (goUp) //lastnode closes the node->parent - { - //handle cases like
- if (lastNode->tag->type == Tag::XmlTagEnd && - !QuantaCommon::closesTag(node->parent->tag, lastNode->tag)) - { - while ( node->parent->parent && - QuantaCommon::closesTag(node->parent->parent->tag, lastNode->tag) - ) + if (goUp) //lastnode closes the node->parent + { + //handle cases like
+ if (lastNode->tag->type == Tag::XmlTagEnd && + !QuantaCommon::closesTag(node->parent->tag, lastNode->tag)) { - node = node->parent; - } - } else - if (qTag && lastNode->tag->type != Tag::XmlTagEnd) - { - //handle the case when a tag is a stopping tag for parent, and grandparent and so on. I'm not sure it's needed here, but anyway... - Node *n = node->parent; - QString searchFor = (m_dtd->caseSensitive) ? lastNode->tag->name : lastNode->tag->name.upper(); - while (qTag && n) + while ( node->parent->parent && + QuantaCommon::closesTag(node->parent->parent->tag, lastNode->tag) + ) + { + node = node->parent; + } + } else + if (qTag && lastNode->tag->type != Tag::XmlTagEnd) { - qTag = QuantaCommon::tagFromDTD(m_dtd, n->tag->name); - if ( qTag ) + //handle the case when a tag is a stopping tag for parent, and grandparent and so on. I'm not sure it's needed here, but anyway... + Node *n = node->parent; + QString searchFor = (m_dtd->caseSensitive) ? lastNode->tag->name : lastNode->tag->name.upper(); + while (qTag && n) { - if ( qTag->stoppingTags.contains(searchFor) ) + qTag = QuantaCommon::tagFromDTD(m_dtd, n->tag->name); + if ( qTag ) { - n->tag->closingMissing = true; //parent is single... - if (n->parent) - node = n; - n = n->parent; - } else - { - break; + if ( qTag->stoppingTags.contains(searchFor) ) + { + n->tag->closingMissing = true; //parent is single... + if (n->parent) + node = n; + n = n->parent; + } else + { + break; + } } } } - } - if (lastNode->prev && lastNode->prev->next == lastNode) - lastNode->prev->next = 0L; - if (lastNode->parent && lastNode->parent->child == lastNode) - lastNode->parent->child = 0L; - node->parent->next = lastNode; - lastNode->prev = node->parent; - if (node->parent) - lastNode->parent = node->parent->parent; - else - lastNode->parent = 0L; - node->next = 0L; - lastNode->closesPrevious = true; - } else - { - if (lastNode->prev && lastNode->prev->next == lastNode) + if (lastNode->prev && lastNode->prev->next == lastNode) lastNode->prev->next = 0L; - node->next = lastNode; - lastNode->prev = node; - lastNode->parent = node->parent; + if (lastNode->parent && lastNode->parent->child == lastNode) + lastNode->parent->child = 0L; + if (node->parent) + node->parent->next = lastNode; + lastNode->prev = node->parent; + if (node->parent) + lastNode->parent = node->parent->parent; + else + lastNode->parent = 0L; + node->next = 0L; + lastNode->closesPrevious = true; + } else + { + if (lastNode->prev && lastNode->prev->next == lastNode) + lastNode->prev->next = 0L; + node->next = lastNode; + lastNode->prev = node; + lastNode->parent = node->parent; +// kdDebug(24000) << "lastNode7: " << lastNode << " " << lastNode->tag << endl; + } + node = lastNode; + lastNode = lastNode->nextNotChild(); + if (lastNode) + QString s = lastNode->tag->tagStr(); } - node = lastNode; - lastNode = lastNode->nextNotChild(); - } } /* kdDebug(24000)<< "END"<< endl; ParserCommon::coutTree(baseNode, 2); @@ -1209,7 +1222,8 @@ w->docUndoRedo->addNewModifsSet(modifs, undoRedo::SourceModif); } kdDebug(24000) << "Rebuild: " << t.elapsed() << " ms; baseNode=" << baseNode << "\n"; - + +// ParserCommon::verifyTree(m_node); /* treeSize = 0; ParserCommon::coutTree(m_node, 2); kdDebug(24000) << "Size of tree: " << treeSize << endl;*/ --- branches/KDE/3.5/kdewebdev/quanta/parsers/parsercommon.cpp #638660:638661 @@ -236,4 +236,21 @@ } } +void verifyTree(Node *node) +{ + QString output; + int bLine, bCol, eLine, eCol; + while (node) + { + if (!node->tag) + { + kdDebug(24000) << "Bad node: " << node << endl; + kdDebug(24000) << "Parent: " << node->parent << " " << node->parent->tag->tagStr() << endl; + } + if (node->child) + verifyTree(node->child); + node = node->next; + } } + +} --- branches/KDE/3.5/kdewebdev/quanta/parsers/parsercommon.h #638660:638661 @@ -53,6 +53,7 @@ /** Print the doc structure tree to the standard output. Only for debugging purposes. */ void coutTree(Node *node, int indent); + void verifyTree(Node *node); } #endif --- branches/KDE/3.5/kdewebdev/quanta/parsers/saparser.cpp #638660:638661 @@ -900,7 +900,8 @@ AreaStruct area(m_currentNode->tag->area()); s_next = 0L; m_useNext = false; - if (m_currentNode->next) + //FIXME: Find out why can the tag become 0L + if (m_currentNode->next && m_currentNode->next->tag) { AreaStruct area2(m_currentNode->next->tag->area()); area.eLine = area2.eLine; --- branches/KDE/3.5/kdewebdev/quanta/quanta.kdevelop #638660:638661 @@ -259,10 +259,10 @@ - + Quanta speicfic header - + A new empty C++ file. --- branches/KDE/3.5/kdewebdev/quanta/src/quanta.cpp #638660:638661 @@ -4274,7 +4274,7 @@ QString tagName; if (node && node->tag) { - Tag *tag = node->tag; + Tag *tag = new Tag(*node->tag); //create a copy, as a reparse might happen meantime and that would make node (and node->tag) invalid tagName = tag->name; if ( QuantaCommon::isKnownTag(tag->dtd()->name,tagName) ) { @@ -4287,7 +4287,7 @@ { w->changeTag(tag, dlg->getAttributes() ); } - + delete tag; delete dlg; } } --- branches/KDE/3.5/kdewebdev/quanta/src/quantaview.cpp #638660:638661 @@ -74,6 +74,8 @@ #include "tagdialog.h" extern int NN; +extern QValueList nodes; + QuantaView::QuantaView(QWidget *parent, const char *name, const QString &caption ) : KMdiChildView(parent, name) , m_document(0L) @@ -143,10 +145,14 @@ if (static_cast(quantaApp->activeWindow()) == this) { parser->setSAParserEnabled(false); - kdDebug(24000) << "Node objects before delete :" << NN << " baseNode= " << baseNode << endl; + kdDebug(24000) << "Node objects before delete = " << NN << " ; list count = " << nodes.count() << endl; delete baseNode; baseNode = 0L; - kdDebug(24000) << "Node objects after delete :" << NN << " baseNode= " << baseNode << endl; + kdDebug(24000) << "Node objects after delete = " << NN << " ; list count = " << nodes.count() << endl; + QValueList nList = nodes; +/* for (QValueList::ConstIterator it = nList.constBegin(); it != nList.constEnd(); ++it) + delete (*it); + kdDebug(24000) << "Node objects after cleanup = " << NN << " ; list count = " << nodes.count() << endl;*/ } if (m_document) {