[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: KDirWatch crash fix
From: David Faure <faure () kde ! org>
Date: 2008-03-15 22:01:19
Message-ID: 200803152301.20459.faure () kde ! org
[Download RAW message or body]
After making some changes to kdirmodeltest I've been hitting a reproduceable crash in KDirWatch.
The problem comes from this code in removeEntry:
if (e->isDir)
removeEntry(0, QDir::cleanPath(e->path+"/.."), e);
else
removeEntry(0, QFileInfo(e->path).absolutePath(), e);
If the entry for that "parent directory" is in removeList (the list of removed deletions)
then when processing that list it will crash, due to looking at an already-deleted entry.
Any objections against the attached patch?
--
David Faure, faure@kde.org, sponsored by Trolltech to work on KDE,
Konqueror (http://www.konqueror.org), and KOffice (http://www.koffice.org).
["kdirwatch.diff" (text/x-diff)]
Index: kdirwatch.cpp
===================================================================
--- kdirwatch.cpp (révision 785348)
+++ kdirwatch.cpp (copie de travail)
@@ -607,8 +607,8 @@
{
if (sub_entry) {
(*it).m_entries.append(sub_entry);
- kDebug(7001) << "Added already watched Entry " << path
- << " (for " << sub_entry->path << ")";
+ kDebug(7001) << "Added already watched Entry" << path
+ << "(for" << sub_entry->path << ")";
#ifdef HAVE_SYS_INOTIFY_H
Entry* e = &(*it);
if( (e->m_mode == INotifyMode) && (e->wd > 0) ) {
@@ -639,10 +639,9 @@
QByteArray tpath (QFile::encodeName(path));
bool exists = (KDE_stat(tpath, &stat_buf) == 0);
- Entry newEntry;
- m_mapEntries.insert( path, newEntry );
+ EntryMap::iterator newIt = m_mapEntries.insert( path, Entry() );
// the insert does a copy, so we have to use <e> now
- Entry* e = &(m_mapEntries[path]);
+ Entry* e = &(*newIt);
if (exists) {
e->isDir = S_ISDIR(stat_buf.st_mode);
@@ -758,10 +757,10 @@
void KDirWatchPrivate::removeEntry( KDirWatch* instance,
- const QString& _path, Entry* sub_entry )
+ const QString& _path, // TODO Entry* e instead
+ Entry* sub_entry )
{
- kDebug(7001) << "KDirWatchPrivate::removeEntry for" << _path
- << "sub_entry:" << sub_entry;
+ kDebug(7001) << "path=" << _path << "sub_entry:" << sub_entry;
Entry* e = entry(_path);
if (!e) {
kWarning(7001) << "KDirWatch::removeDir can't handle"
@@ -785,6 +784,8 @@
return;
}
+ removeList.removeAll(e);
+
#ifdef HAVE_FAM
if (e->m_mode == FAMMode) {
if ( e->m_status == Normal) {
@@ -1117,9 +1118,13 @@
void KDirWatchPrivate::slotRemoveDelayed()
{
delayRemove = false;
- foreach(Entry* e, removeList)
+ // Removing an entry could also take care of removing its parent
+ // (e.g. in FAM or inotify mode), which would remove other entries in removeList,
+ // so don't use foreach or iterators here...
+ while (!removeList.isEmpty()) {
+ Entry* e = removeList.takeFirst();
removeEntry(0, e->path, 0);
- removeList.clear();
+ }
}
/* Scan all entries to be watched for changes. This is done regularly
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic