diff --git a/doc/Changelog.html b/doc/Changelog.html
index 266383b6..055cfc62 100644
--- a/doc/Changelog.html
+++ b/doc/Changelog.html
@@ -21,6 +21,7 @@ a:visited { color: #0000EE; }
Updated Qt runtime libraries to v4.8.5 (2013-05-31), compiled with MSVC 11.0
Updated FLAC encoder/decoder to v1.3.0 (2013-05-27), compiled with ICL 13.0
Updated Opus encoder/decoder libraries to v1.1.x and Opus-Tools to v0.1.6 (2013-06-17)
+Fixed a potential deadlock during startup when %TMP% points to an invalid folder
Fixed a superfluous "beep" sound that appeared on application startup
diff --git a/src/Config.h b/src/Config.h
index d9e3f7a9..c671e6c8 100644
--- a/src/Config.h
+++ b/src/Config.h
@@ -34,7 +34,7 @@
#define VER_LAMEXP_MINOR_LO 8
#define VER_LAMEXP_TYPE Alpha
#define VER_LAMEXP_PATCH 3
-#define VER_LAMEXP_BUILD 1298
+#define VER_LAMEXP_BUILD 1301
#define VER_LAMEXP_CONFG 1288
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/Dialog_SplashScreen.cpp b/src/Dialog_SplashScreen.cpp
index 07345b45..c1b02ee3 100644
--- a/src/Dialog_SplashScreen.cpp
+++ b/src/Dialog_SplashScreen.cpp
@@ -144,12 +144,14 @@ void SplashScreen::showSplash(QThread *thread)
//Loop while thread is still running
if(bool bIsRunning = THREAD_RUNNING(thread))
{
+ int deadlockCounter = 0;
while(bIsRunning)
{
loop->exec();
if(bIsRunning = THREAD_RUNNING(thread))
{
qWarning("Potential deadlock in initialization thread!");
+ if(++deadlockCounter >= 10) qFatal("Deadlock in initialization thread!");
}
}
}
diff --git a/src/Global.cpp b/src/Global.cpp
index ad8c755d..d901ef69 100644
--- a/src/Global.cpp
+++ b/src/Global.cpp
@@ -228,11 +228,18 @@ static const unsigned int g_lamexp_toolver_coreaudio = VER_LAMEXP_TOOL_COREAUDIO
//Special folders
static struct
{
- QString *temp;
QMap *knownFolders;
QReadWriteLock lock;
}
-g_lamexp_folder;
+g_lamexp_known_folder;
+
+//%TEMP% folder
+static struct
+{
+ QString *path;
+ QReadWriteLock lock;
+}
+g_lamexp_temp_folder;
//Tools
static struct
@@ -1487,102 +1494,103 @@ QString lamexp_rand_str(void)
throw "The RegExp didn't match on the UUID string. This shouldn't happen ;-)";
}
+
+/*
+ * Try to initialize the folder (with *write* access)
+ */
+static QString lamexp_try_init_folder(const QString &folderPath)
+{
+ bool success = false;
+
+ const QFileInfo folderInfo(folderPath);
+ const QDir folderDir(folderInfo.absoluteFilePath());
+
+ //Create folder, if it does *not* exist yet
+ if(!folderDir.exists())
+ {
+ folderDir.mkpath(".");
+ }
+
+ //Make sure folder exists now *and* is writable
+ if(folderDir.exists())
+ {
+ QFile testFile(folderDir.absoluteFilePath(QString("~%1.tmp").arg(lamexp_rand_str())));
+ if(testFile.open(QIODevice::ReadWrite))
+ {
+ const QByteArray testData = QByteArray("Lorem ipsum dolor sit amet, consectetur, adipisci velit!");
+ if(testFile.write(testData) >= strlen(testData))
+ {
+ success = true;
+ testFile.remove();
+ }
+ testFile.close();
+ }
+ }
+
+ return (success ? folderDir.canonicalPath() : QString());
+}
+
/*
* Get LameXP temp folder
*/
const QString &lamexp_temp_folder2(void)
{
- QReadLocker readLock(&g_lamexp_folder.lock);
+ QReadLocker readLock(&g_lamexp_temp_folder.lock);
//Already initialized?
- if(g_lamexp_folder.temp)
+ if(g_lamexp_temp_folder.path && (!g_lamexp_temp_folder.path->isEmpty()))
{
- if(!g_lamexp_folder.temp->isEmpty())
+ if(QDir(*g_lamexp_temp_folder.path).exists())
{
- if(QDir(*g_lamexp_folder.temp).exists())
- {
- return *g_lamexp_folder.temp;
- }
+ return *g_lamexp_temp_folder.path;
}
}
-
+
+ //Obtain the write lock to initilaize
readLock.unlock();
- QWriteLocker writeLock(&g_lamexp_folder.lock);
+ QWriteLocker writeLock(&g_lamexp_temp_folder.lock);
- if(!g_lamexp_folder.temp)
+ //Still uninitilaized?
+ if(g_lamexp_temp_folder.path && (!g_lamexp_temp_folder.path->isEmpty()))
{
- g_lamexp_folder.temp = new QString();
+ if(QDir(*g_lamexp_temp_folder.path).exists())
+ {
+ return *g_lamexp_temp_folder.path;
+ }
+ }
+
+ //Create the string, if not done yet
+ if(!g_lamexp_temp_folder.path)
+ {
+ g_lamexp_temp_folder.path = new QString();
}
- g_lamexp_folder.temp->clear();
-
- static const char *TEMP_STR = "Temp";
- const QString WRITE_TEST_DATA = lamexp_rand_str();
- const QString SUB_FOLDER = lamexp_rand_str();
+ g_lamexp_temp_folder.path->clear();
//Try the %TMP% or %TEMP% directory first
- QDir temp = QDir::temp();
- if(temp.exists())
+ QString tempPath = lamexp_try_init_folder(QDir::temp().absolutePath());
+ if(!tempPath.isEmpty())
{
- temp.mkdir(SUB_FOLDER);
- if(temp.cd(SUB_FOLDER) && temp.exists())
+ (*g_lamexp_temp_folder.path) = lamexp_try_init_folder(QString("%1/%2").arg(tempPath, lamexp_rand_str()));
+ }
+
+ //Otherwise create TEMP folder in %LOCALAPPDATA%
+ if(g_lamexp_temp_folder.path->isEmpty())
+ {
+ tempPath = lamexp_try_init_folder(QString("%1/Temp").arg(lamexp_known_folder(lamexp_folder_localappdata)));
+ if(!tempPath.isEmpty())
{
- QFile testFile(QString("%1/~%2.tmp").arg(temp.canonicalPath(), lamexp_rand_str()));
- if(testFile.open(QIODevice::ReadWrite))
- {
- if(testFile.write(WRITE_TEST_DATA.toLatin1().constData()) >= strlen(WRITE_TEST_DATA.toLatin1().constData()))
- {
- (*g_lamexp_folder.temp) = temp.canonicalPath();
- }
- testFile.remove();
- }
- }
- if(!g_lamexp_folder.temp->isEmpty())
- {
- return *g_lamexp_folder.temp;
+ (*g_lamexp_temp_folder.path) = lamexp_try_init_folder(QString("%1/%2").arg(tempPath, lamexp_rand_str()));
}
}
- //Create TEMP folder in %LOCALAPPDATA%
- QDir localAppData = QDir(lamexp_known_folder(lamexp_folder_localappdata));
- if(!localAppData.path().isEmpty())
+ //Failed to create TEMP folder?
+ if(g_lamexp_temp_folder.path->isEmpty())
{
- if(!localAppData.exists())
- {
- localAppData.mkpath(".");
- }
- if(localAppData.exists())
- {
- if(!localAppData.entryList(QDir::AllDirs).contains(TEMP_STR, Qt::CaseInsensitive))
- {
- localAppData.mkdir(TEMP_STR);
- }
- if(localAppData.cd(TEMP_STR) && localAppData.exists())
- {
- localAppData.mkdir(SUB_FOLDER);
- if(localAppData.cd(SUB_FOLDER) && localAppData.exists())
- {
- QFile testFile(QString("%1/~%2.tmp").arg(localAppData.canonicalPath(), lamexp_rand_str()));
- if(testFile.open(QIODevice::ReadWrite))
- {
- if(testFile.write(WRITE_TEST_DATA.toLatin1().constData()) >= strlen(WRITE_TEST_DATA.toLatin1().constData()))
- {
- (*g_lamexp_folder.temp) = localAppData.canonicalPath();
- }
- testFile.remove();
- }
- }
- }
- }
- if(!g_lamexp_folder.temp->isEmpty())
- {
- return *g_lamexp_folder.temp;
- }
+ qFatal("Temporary directory could not be initialized !!!");
}
-
- //Failed to create TEMP folder!
- qFatal("Temporary directory could not be initialized!\n\nFirst attempt:\n%s\n\nSecond attempt:\n%s", temp.canonicalPath().toUtf8().constData(), localAppData.canonicalPath().toUtf8().constData());
- return *g_lamexp_folder.temp;
+
+ return *g_lamexp_temp_folder.path;
}
/*
@@ -1908,7 +1916,7 @@ const QString &lamexp_known_folder(lamexp_known_folder_t folder_id)
static const GUID GUID_PROGRAM_FILES = {0x905e63b6,0xc1bf,0x494e,{0xb2,0x9c,0x65,0xb7,0x32,0xd3,0xd2,0x1a}};
static const GUID GUID_SYSTEM_FOLDER = {0x1AC14E77,0x02E7,0x4E5D,{0xB7,0x44,0x2E,0xB1,0xAE,0x51,0x98,0xB7}};
- QReadLocker readLock(&g_lamexp_folder.lock);
+ QReadLocker readLock(&g_lamexp_known_folder.lock);
int folderCSIDL = -1;
GUID folderGUID = {0x0000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}};
@@ -1938,20 +1946,31 @@ const QString &lamexp_known_folder(lamexp_known_folder_t folder_id)
}
//Already in cache?
- if(g_lamexp_folder.knownFolders)
+ if(g_lamexp_known_folder.knownFolders)
{
- if(g_lamexp_folder.knownFolders->contains(folderCacheId))
+ if(g_lamexp_known_folder.knownFolders->contains(folderCacheId))
{
- return (*g_lamexp_folder.knownFolders)[folderCacheId];
+ return (*g_lamexp_known_folder.knownFolders)[folderCacheId];
}
}
+ //Obtain write lock to initialize
readLock.unlock();
- QWriteLocker writeLock(&g_lamexp_folder.lock);
+ QWriteLocker writeLock(&g_lamexp_known_folder.lock);
+
+ //Still not in cache?
+ if(g_lamexp_known_folder.knownFolders)
+ {
+ if(g_lamexp_known_folder.knownFolders->contains(folderCacheId))
+ {
+ return (*g_lamexp_known_folder.knownFolders)[folderCacheId];
+ }
+ }
static SHGetKnownFolderPathFun SHGetKnownFolderPathPtr = NULL;
static SHGetFolderPathFun SHGetFolderPathPtr = NULL;
+ //Lookup functions
if((!SHGetKnownFolderPathPtr) && (!SHGetFolderPathPtr))
{
QLibrary kernel32Lib("shell32.dll");
@@ -1964,6 +1983,7 @@ const QString &lamexp_known_folder(lamexp_known_folder_t folder_id)
QString folder;
+ //Now try to get the folder path!
if(SHGetKnownFolderPathPtr)
{
WCHAR *path = NULL;
@@ -2002,14 +2022,14 @@ const QString &lamexp_known_folder(lamexp_known_folder_t folder_id)
}
//Create cache
- if(!g_lamexp_folder.knownFolders)
+ if(!g_lamexp_known_folder.knownFolders)
{
- g_lamexp_folder.knownFolders = new QMap();
+ g_lamexp_known_folder.knownFolders = new QMap();
}
//Update cache
- g_lamexp_folder.knownFolders->insert(folderCacheId, folder);
- return (*g_lamexp_folder.knownFolders)[folderCacheId];
+ g_lamexp_known_folder.knownFolders->insert(folderCacheId, folder);
+ return (*g_lamexp_known_folder.knownFolders)[folderCacheId];
}
/*
@@ -2434,7 +2454,8 @@ extern "C"
LAMEXP_ZERO_MEMORY(g_lamexp_tools);
LAMEXP_ZERO_MEMORY(g_lamexp_currentTranslator);
LAMEXP_ZERO_MEMORY(g_lamexp_translation);
- LAMEXP_ZERO_MEMORY(g_lamexp_folder);
+ LAMEXP_ZERO_MEMORY(g_lamexp_known_folder);
+ LAMEXP_ZERO_MEMORY(g_lamexp_temp_folder);
LAMEXP_ZERO_MEMORY(g_lamexp_ipc_ptr);
LAMEXP_ZERO_MEMORY(g_lamexp_os_version);
LAMEXP_ZERO_MEMORY(g_lamexp_themes_enabled);
@@ -2501,24 +2522,24 @@ void lamexp_finalization(void)
}
//Delete temporary files
- if(g_lamexp_folder.temp)
+ if(g_lamexp_temp_folder.path)
{
- if(!g_lamexp_folder.temp->isEmpty())
+ if(!g_lamexp_temp_folder.path->isEmpty())
{
for(int i = 0; i < 100; i++)
{
- if(lamexp_clean_folder(*g_lamexp_folder.temp))
+ if(lamexp_clean_folder(*g_lamexp_temp_folder.path))
{
break;
}
Sleep(125);
}
}
- LAMEXP_DELETE(g_lamexp_folder.temp);
+ LAMEXP_DELETE(g_lamexp_temp_folder.path);
}
//Clear folder cache
- LAMEXP_DELETE(g_lamexp_folder.knownFolders);
+ LAMEXP_DELETE(g_lamexp_known_folder.knownFolders);
//Clear languages
if(g_lamexp_currentTranslator.instance)
diff --git a/src/Thread_Initialization.cpp b/src/Thread_Initialization.cpp
index 0a226c0f..5af7da6b 100644
--- a/src/Thread_Initialization.cpp
+++ b/src/Thread_Initialization.cpp
@@ -297,6 +297,10 @@ void InitializationThread::run()
qWarning("Extracting tools took %.3f seconds -> probably slow realtime virus scanner.", delayExtract);
qWarning("Please report performance problems to your anti-virus developer !!!\n");
}
+ else
+ {
+ qDebug("Extracting the tools took %.3f seconds (OK).\n", delayExtract);
+ }
//Register all translations
initTranslations();