forked from qt-creator/qt-creator
Fix crashes when loading large .qmlproject's (Mac OS X)
There is a hard limit on the number of file handles that can be open at one point per process on Mac OS X (e.g. it's 2560 on Mac OS X Snow Leopard Server, as shown by ulimit -a). Opening one or several .qmlproject's with a large number of directories to watch easily exceeds this. The results are crashes later on, e.g. when threads cannot be created any more. This patch implements a heuristic that the file system watcher used for .qmlproject files never uses more than half the number of available file handles. It also increases the number from rlim_cur to rlim_max - the old code in main.cpp failed, see last section in http://developer.apple.com/maac/library/documentation/Darwin/Reference/ManPages/man2/setrlimit.2.html for details. Reviewed-by: ckamm Task-number: QTCREATORBUG-1487 Task-number: QTCREATORBUG-1486
This commit is contained in:
@@ -173,7 +173,8 @@ int main(int argc, char **argv)
|
|||||||
// increase the number of file that can be opened in Qt Creator.
|
// increase the number of file that can be opened in Qt Creator.
|
||||||
struct rlimit rl;
|
struct rlimit rl;
|
||||||
getrlimit(RLIMIT_NOFILE, &rl);
|
getrlimit(RLIMIT_NOFILE, &rl);
|
||||||
rl.rlim_cur = rl.rlim_max;
|
|
||||||
|
rl.rlim_cur = qMin((rlim_t)OPEN_MAX, rl.rlim_max);
|
||||||
setrlimit(RLIMIT_NOFILE, &rl);
|
setrlimit(RLIMIT_NOFILE, &rl);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,19 @@ void FileSystemWatcher::addFile(const QString &file)
|
|||||||
addFiles(QStringList(file));
|
addFiles(QStringList(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
|
||||||
|
// Returns upper limit of file handles that can be opened by this process at once. Exceeding it will probably result in crashes!
|
||||||
|
static rlim_t getFileLimit()
|
||||||
|
{
|
||||||
|
struct rlimit rl;
|
||||||
|
getrlimit(RLIMIT_NOFILE, &rl);
|
||||||
|
return rl.rlim_cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void FileSystemWatcher::addFiles(const QStringList &files)
|
void FileSystemWatcher::addFiles(const QStringList &files)
|
||||||
{
|
{
|
||||||
QStringList toAdd;
|
QStringList toAdd;
|
||||||
@@ -84,6 +97,17 @@ void FileSystemWatcher::addFiles(const QStringList &files)
|
|||||||
qWarning() << "FileSystemWatcher: File" << file << "is already being watched";
|
qWarning() << "FileSystemWatcher: File" << file << "is already being watched";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
static rlim_t maxFileOpen = getFileLimit();
|
||||||
|
// We're potentially watching a _lot_ of directories. This might crash qtcreator when we hit the upper limit.
|
||||||
|
// Heuristic is therefore: Don't use more than half of the file handles available in this watcher
|
||||||
|
if ((rlim_t)m_directories.size() + (rlim_t)m_files.size() > maxFileOpen / 2) {
|
||||||
|
qWarning() << "File" << file << "is not watched: Too many file handles are already open (max is" << maxFileOpen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m_files.append(file);
|
m_files.append(file);
|
||||||
|
|
||||||
const int count = ++m_fileCount[file];
|
const int count = ++m_fileCount[file];
|
||||||
@@ -149,6 +173,17 @@ void FileSystemWatcher::addDirectories(const QStringList &directories)
|
|||||||
qWarning() << "Directory" << directory << "is already being watched";
|
qWarning() << "Directory" << directory << "is already being watched";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
static rlim_t maxFileOpen = getFileLimit();
|
||||||
|
// We're potentially watching a _lot_ of directories. This might crash qtcreator when we hit the upper limit.
|
||||||
|
// Heuristic is therefore: Don't use more than half of the file handles available in this watcher
|
||||||
|
if ((rlim_t)m_directories.size() + (rlim_t)m_files.size() > maxFileOpen / 2) {
|
||||||
|
qWarning() << "Directory" << directory << "is not watched: Too many file handles are already open (max is" << maxFileOpen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m_directories.append(directory);
|
m_directories.append(directory);
|
||||||
|
|
||||||
const int count = ++m_directoryCount[directory];
|
const int count = ++m_directoryCount[directory];
|
||||||
|
|||||||
Reference in New Issue
Block a user