PDA

View Full Version : canonicalFilePath() thread problems



magland
13th July 2007, 04:14
Using 4.2.1, I ran into some wierd problems running

fname2=QFileInfo(fname).canonicalFilePath()
with multiple threads. The function was occasionally getting mixed up between threads and returning incorrect results.

So, I mutex'ed it out and everything was fixed. But it was a big deal because I had to use the same mutex on every occurance of QFileInfo throughout my application. I thought that QFileInfo was supposed to be re-entrant ....?

jpn
13th July 2007, 08:33
What happens if you set caching off or call refresh() before canonicalFilePath()? I know this is not a solution but I'm curious if it's just a caching problem.

magland
13th July 2007, 12:21
What happens if you set caching off or call refresh() before canonicalFilePath()? I know this is not a solution but I'm curious if it's just a caching problem.

Unfortunately (or fortunately, depending on how you look at it)... now that I've made a separate function in my class called "canonical" (for purpose of mutexing the QFileInfo(str).canonicalFilePath()), I can't get it to fail again, --- even without the QMutexLocker :eek: So I don't have an answer, but I think I'll keep the mutex locker in there to be safe... it seems like a not completely reproducible potential bug.... the worst kind.

magland
13th July 2007, 12:57
What happens if you set caching off or call refresh() before canonicalFilePath()? I know this is not a solution but I'm curious if it's just a caching problem.

Sorry, I spoke too soon on that last post. It IS reproducible, and locking the QMutex IS required. But the refresh() and setCaching(off) does not seem to do the trick, because if I comment out the QMutexLocker line and uncomment the other two lines below, I get the problem.



QString canonical(QString str) { //this seems to be necesary due to wierd thread problems
QMutexLocker locker(&canonical_mutex);
QFileInfo info(str);
//info.setCaching(false);
//info.refresh();
return info.canonicalFilePath();
}

magland
29th November 2007, 12:38
Just wanted to follow up on this thread and point out that I am still suffering from thread-related problems with QFileInfo. Functions like canonicalFilePath() simply return the wrong data (rarely, but consistently)

As a workaround I created a MyQFileInfo class in which I mutex out all the key functions, and it works fine.

So this is a warning to everyone using QFileInfo with threads.

jacek
29th November 2007, 13:55
Functions like canonicalFilePath() simply return the wrong data (rarely, but consistently)
Which Qt version do you use?

magland
29th November 2007, 20:56
Which Qt version do you use?

4.3.2 now. In the past I used 4.3.0, same problem.

Again, problem only arises with multiple threads, and is resolved by locking mutexes.

J

jacek
29th November 2007, 21:21
4.3.2 now. In the past I used 4.3.0, same problem.
The docs say that QFileInfo is reentrant and they don't say that it isn't thread-safe, so it should work. There were some problems with QFileInfo in the past (see task #103940 (http://trolltech.com/developer/task-tracker/index_html?method=entry&id=103940)), so this might be a bug that should be reported to the Trolls.

magland
30th November 2007, 21:20
The docs say that QFileInfo is reentrant and they don't say that it isn't thread-safe, so it should work. There were some problems with QFileInfo in the past (see task #103940 (http://trolltech.com/developer/task-tracker/index_html?method=entry&id=103940)), so this might be a bug that should be reported to the Trolls.

Okay, I reported it. Thanks.

magland
4th December 2007, 13:05
I was able to reproduce the problem with a single main.cpp (below). I reported to Trolltech, but feel free to try it out on your system. I am using Windows XP.



#include <QtGui>
#include <QDir>

///Change these as needed
#define SAMPLE_DIRECTORY_1 "c:\\"
#define SAMPLE_DIRECTORY_2 "c:\\jer"
#define NUM_REPEATS 100
///When DO_LOCK_MUTEX is turned off, inconsistencies are displayed on my system
//#define DO_LOCK_MUTEX

static QMutex my_mutex;

class MyThread1 : public QThread
{
public:
void run()
{
QString dirname=SAMPLE_DIRECTORY_1;
QDir dir(dirname);
QStringList list=dir.entryList(QStringList("*"));
for (int j=0; j<NUM_REPEATS; j++) {
foreach (QString F,list) {
#ifdef DO_LOCK_MUTEX
my_mutex.lock();
#endif
QString path=dirname+"/"+F;
QString str1=QFileInfo(path).canonicalFilePath();
QString str2=QFileInfo(path).canonicalFilePath();
if (str1!=str2) {
qDebug() << "~!!!!!!!!!!!!!!!!! Inconsistency with" << str1 << str2;
}
#ifdef DO_LOCK_MUTEX
my_mutex.unlock();
#endif
}
}
}
};

class MyThread2 : public QThread
{
public:
void run()
{
QString dirname=SAMPLE_DIRECTORY_2;
QDir dir(dirname);
QStringList list=dir.entryList(QStringList("*"));
for (int j=0; j<NUM_REPEATS; j++) {
foreach (QString F,list) {
#ifdef DO_LOCK_MUTEX
my_mutex.lock();
#endif
QString path=dirname+"/"+F;
QString str1=QFileInfo(path).canonicalFilePath();
QString str2=QFileInfo(path).canonicalFilePath();
if (str1!=str2) {
qDebug() << "~!!!!!!!!!!!!!!!!! Inconsistency with" << str1 << str2;
}
#ifdef DO_LOCK_MUTEX
my_mutex.unlock();
#endif
}
}
}
};





int main(int argc, char **argv)
{
QApplication app(argc, argv);
QWidget wid;
wid.show();
MyThread1 T1;
MyThread2 T2;
T1.start();
T2.start();

qDebug() << "Looking for inconsistencies in QFileInfo::canonicalFilePath()";


return app.exec();
}

magland
5th December 2007, 22:22
For information, trolls have acknowledged the problem and are now working on it.