Commit 42e2070925d012845db9cf85e597a17851a0dcb6

Fix leak of file descriptors in QTemporaryFile

Using setFileName in QFile::copy (introduced recently) has a nasty
side-effect of leaking file descriptors in QTemporaryFile. This happens
because the code assumes the file has been closed. In QTemporaryFile,
we need to explicitly call native file engine close.

Test case by Thiago. Bug report from Arora developers.

Reviewed-by: thiago
  
294294 QTemporaryFileEngine(const QString &file) : QFSFileEngine(file) { }
295295 ~QTemporaryFileEngine();
296296
297 void setFileName(const QString &file);
298
297299 bool open(QIODevice::OpenMode flags);
298300 bool remove();
299301 bool close();
304304QTemporaryFileEngine::~QTemporaryFileEngine()
305305{
306306 QFSFileEngine::close();
307}
308
309void QTemporaryFileEngine::setFileName(const QString &file)
310{
311 // Really close the file, so we don't leak
312 QFSFileEngine::close();
313 QFSFileEngine::setFileName(file);
307314}
308315
309316bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  
11load(qttest_p4)
22SOURCES += tst_qtemporaryfile.cpp
33QT = core
4
5DEFINES += SRCDIR=\\\"$$PWD/\\\"
  
5151#if defined(Q_OS_WIN)
5252# include <windows.h>
5353#endif
54#if defined(Q_OS_UNIX)
55# include <sys/types.h>
56# include <sys/stat.h>
57# include <errno.h>
58# include <fcntl.h> // open(2)
59# include <unistd.h> // close(2)
60#endif
5461
5562//TESTED_CLASS=
5663//TESTED_FILES=
8585 void openOnRootDrives();
8686 void stressTest();
8787 void rename();
88 void renameFdLeak();
8889public:
8990};
9091
362362
363363 QVERIFY(!dir.exists(tempname));
364364 QVERIFY(!dir.exists("temporary-file.txt"));
365}
366
367void tst_QTemporaryFile::renameFdLeak()
368{
369#ifdef Q_OS_UNIX
370 // Test this on Unix only
371
372 // Open a bunch of files to force the fd count to go up
373 static const int count = 10;
374 int bunch_of_files[count];
375 for (int i = 0; i < count; ++i) {
376 bunch_of_files[i] = ::open(SRCDIR "tst_qtemporaryfile.cpp", O_RDONLY);
377 QVERIFY(bunch_of_files[i] != -1);
378 }
379
380 int fd;
381 {
382 QTemporaryFile file;
383 file.setAutoRemove(false);
384 QVERIFY(file.open());
385
386 // close the bunch of files
387 for (int i = 0; i < count; ++i)
388 ::close(bunch_of_files[i]);
389
390 // save the file descriptor for later
391 fd = file.handle();
392
393 // rename the file to something
394 QString newPath = QDir::tempPath() + "/tst_qtemporaryfile-renameFdLeak-" + QString::number(getpid());
395 file.rename(newPath);
396 QFile::remove(newPath);
397 }
398
399 // check if QTemporaryFile closed the file
400 QVERIFY(::close(fd) == -1 && errno == EBADF);
401#endif
365402}
366403
367404QTEST_MAIN(tst_QTemporaryFile)