Refactored lamexp_temp_folder2() function. This also fixes a potential deadlock at application when %TMP% points to an invalid folder. Now using separate locks for lamexp_temp_folder2() and lamexp_known_folder().
This commit is contained in:
parent
03c2a9fccc
commit
a8348b01e8
@ -21,6 +21,7 @@ a:visited { color: #0000EE; }
|
|||||||
<li>Updated Qt runtime libraries to v4.8.5 (2013-05-31), compiled with MSVC 11.0
|
<li>Updated Qt runtime libraries to v4.8.5 (2013-05-31), compiled with MSVC 11.0
|
||||||
<li>Updated FLAC encoder/decoder to v1.3.0 (2013-05-27), compiled with ICL 13.0
|
<li>Updated FLAC encoder/decoder to v1.3.0 (2013-05-27), compiled with ICL 13.0
|
||||||
<li>Updated Opus encoder/decoder libraries to v1.1.x and Opus-Tools to v0.1.6 (2013-06-17)
|
<li>Updated Opus encoder/decoder libraries to v1.1.x and Opus-Tools to v0.1.6 (2013-06-17)
|
||||||
|
<li>Fixed a potential deadlock during startup when %TMP% points to an invalid folder
|
||||||
<li>Fixed a superfluous "beep" sound that appeared on application startup
|
<li>Fixed a superfluous "beep" sound that appeared on application startup
|
||||||
</ul><br>
|
</ul><br>
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
#define VER_LAMEXP_MINOR_LO 8
|
#define VER_LAMEXP_MINOR_LO 8
|
||||||
#define VER_LAMEXP_TYPE Alpha
|
#define VER_LAMEXP_TYPE Alpha
|
||||||
#define VER_LAMEXP_PATCH 3
|
#define VER_LAMEXP_PATCH 3
|
||||||
#define VER_LAMEXP_BUILD 1298
|
#define VER_LAMEXP_BUILD 1301
|
||||||
#define VER_LAMEXP_CONFG 1288
|
#define VER_LAMEXP_CONFG 1288
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -144,12 +144,14 @@ void SplashScreen::showSplash(QThread *thread)
|
|||||||
//Loop while thread is still running
|
//Loop while thread is still running
|
||||||
if(bool bIsRunning = THREAD_RUNNING(thread))
|
if(bool bIsRunning = THREAD_RUNNING(thread))
|
||||||
{
|
{
|
||||||
|
int deadlockCounter = 0;
|
||||||
while(bIsRunning)
|
while(bIsRunning)
|
||||||
{
|
{
|
||||||
loop->exec();
|
loop->exec();
|
||||||
if(bIsRunning = THREAD_RUNNING(thread))
|
if(bIsRunning = THREAD_RUNNING(thread))
|
||||||
{
|
{
|
||||||
qWarning("Potential deadlock in initialization thread!");
|
qWarning("Potential deadlock in initialization thread!");
|
||||||
|
if(++deadlockCounter >= 10) qFatal("Deadlock in initialization thread!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
197
src/Global.cpp
197
src/Global.cpp
@ -228,11 +228,18 @@ static const unsigned int g_lamexp_toolver_coreaudio = VER_LAMEXP_TOOL_COREAUDIO
|
|||||||
//Special folders
|
//Special folders
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
QString *temp;
|
|
||||||
QMap<size_t, QString> *knownFolders;
|
QMap<size_t, QString> *knownFolders;
|
||||||
QReadWriteLock lock;
|
QReadWriteLock lock;
|
||||||
}
|
}
|
||||||
g_lamexp_folder;
|
g_lamexp_known_folder;
|
||||||
|
|
||||||
|
//%TEMP% folder
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
QString *path;
|
||||||
|
QReadWriteLock lock;
|
||||||
|
}
|
||||||
|
g_lamexp_temp_folder;
|
||||||
|
|
||||||
//Tools
|
//Tools
|
||||||
static struct
|
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 ;-)";
|
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
|
* Get LameXP temp folder
|
||||||
*/
|
*/
|
||||||
const QString &lamexp_temp_folder2(void)
|
const QString &lamexp_temp_folder2(void)
|
||||||
{
|
{
|
||||||
QReadLocker readLock(&g_lamexp_folder.lock);
|
QReadLocker readLock(&g_lamexp_temp_folder.lock);
|
||||||
|
|
||||||
//Already initialized?
|
//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_temp_folder.path;
|
||||||
{
|
|
||||||
return *g_lamexp_folder.temp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Obtain the write lock to initilaize
|
||||||
readLock.unlock();
|
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();
|
g_lamexp_temp_folder.path->clear();
|
||||||
|
|
||||||
static const char *TEMP_STR = "Temp";
|
|
||||||
const QString WRITE_TEST_DATA = lamexp_rand_str();
|
|
||||||
const QString SUB_FOLDER = lamexp_rand_str();
|
|
||||||
|
|
||||||
//Try the %TMP% or %TEMP% directory first
|
//Try the %TMP% or %TEMP% directory first
|
||||||
QDir temp = QDir::temp();
|
QString tempPath = lamexp_try_init_folder(QDir::temp().absolutePath());
|
||||||
if(temp.exists())
|
if(!tempPath.isEmpty())
|
||||||
{
|
{
|
||||||
temp.mkdir(SUB_FOLDER);
|
(*g_lamexp_temp_folder.path) = lamexp_try_init_folder(QString("%1/%2").arg(tempPath, lamexp_rand_str()));
|
||||||
if(temp.cd(SUB_FOLDER) && temp.exists())
|
}
|
||||||
|
|
||||||
|
//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()));
|
(*g_lamexp_temp_folder.path) = lamexp_try_init_folder(QString("%1/%2").arg(tempPath, 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create TEMP folder in %LOCALAPPDATA%
|
//Failed to create TEMP folder?
|
||||||
QDir localAppData = QDir(lamexp_known_folder(lamexp_folder_localappdata));
|
if(g_lamexp_temp_folder.path->isEmpty())
|
||||||
if(!localAppData.path().isEmpty())
|
|
||||||
{
|
{
|
||||||
if(!localAppData.exists())
|
qFatal("Temporary directory could not be initialized !!!");
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Failed to create TEMP folder!
|
return *g_lamexp_temp_folder.path;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -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_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}};
|
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;
|
int folderCSIDL = -1;
|
||||||
GUID folderGUID = {0x0000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}};
|
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?
|
//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();
|
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 SHGetKnownFolderPathFun SHGetKnownFolderPathPtr = NULL;
|
||||||
static SHGetFolderPathFun SHGetFolderPathPtr = NULL;
|
static SHGetFolderPathFun SHGetFolderPathPtr = NULL;
|
||||||
|
|
||||||
|
//Lookup functions
|
||||||
if((!SHGetKnownFolderPathPtr) && (!SHGetFolderPathPtr))
|
if((!SHGetKnownFolderPathPtr) && (!SHGetFolderPathPtr))
|
||||||
{
|
{
|
||||||
QLibrary kernel32Lib("shell32.dll");
|
QLibrary kernel32Lib("shell32.dll");
|
||||||
@ -1964,6 +1983,7 @@ const QString &lamexp_known_folder(lamexp_known_folder_t folder_id)
|
|||||||
|
|
||||||
QString folder;
|
QString folder;
|
||||||
|
|
||||||
|
//Now try to get the folder path!
|
||||||
if(SHGetKnownFolderPathPtr)
|
if(SHGetKnownFolderPathPtr)
|
||||||
{
|
{
|
||||||
WCHAR *path = NULL;
|
WCHAR *path = NULL;
|
||||||
@ -2002,14 +2022,14 @@ const QString &lamexp_known_folder(lamexp_known_folder_t folder_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Create cache
|
//Create cache
|
||||||
if(!g_lamexp_folder.knownFolders)
|
if(!g_lamexp_known_folder.knownFolders)
|
||||||
{
|
{
|
||||||
g_lamexp_folder.knownFolders = new QMap<size_t, QString>();
|
g_lamexp_known_folder.knownFolders = new QMap<size_t, QString>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Update cache
|
//Update cache
|
||||||
g_lamexp_folder.knownFolders->insert(folderCacheId, folder);
|
g_lamexp_known_folder.knownFolders->insert(folderCacheId, folder);
|
||||||
return (*g_lamexp_folder.knownFolders)[folderCacheId];
|
return (*g_lamexp_known_folder.knownFolders)[folderCacheId];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2434,7 +2454,8 @@ extern "C"
|
|||||||
LAMEXP_ZERO_MEMORY(g_lamexp_tools);
|
LAMEXP_ZERO_MEMORY(g_lamexp_tools);
|
||||||
LAMEXP_ZERO_MEMORY(g_lamexp_currentTranslator);
|
LAMEXP_ZERO_MEMORY(g_lamexp_currentTranslator);
|
||||||
LAMEXP_ZERO_MEMORY(g_lamexp_translation);
|
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_ipc_ptr);
|
||||||
LAMEXP_ZERO_MEMORY(g_lamexp_os_version);
|
LAMEXP_ZERO_MEMORY(g_lamexp_os_version);
|
||||||
LAMEXP_ZERO_MEMORY(g_lamexp_themes_enabled);
|
LAMEXP_ZERO_MEMORY(g_lamexp_themes_enabled);
|
||||||
@ -2501,24 +2522,24 @@ void lamexp_finalization(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Delete temporary files
|
//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++)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
Sleep(125);
|
Sleep(125);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LAMEXP_DELETE(g_lamexp_folder.temp);
|
LAMEXP_DELETE(g_lamexp_temp_folder.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clear folder cache
|
//Clear folder cache
|
||||||
LAMEXP_DELETE(g_lamexp_folder.knownFolders);
|
LAMEXP_DELETE(g_lamexp_known_folder.knownFolders);
|
||||||
|
|
||||||
//Clear languages
|
//Clear languages
|
||||||
if(g_lamexp_currentTranslator.instance)
|
if(g_lamexp_currentTranslator.instance)
|
||||||
|
@ -297,6 +297,10 @@ void InitializationThread::run()
|
|||||||
qWarning("Extracting tools took %.3f seconds -> probably slow realtime virus scanner.", delayExtract);
|
qWarning("Extracting tools took %.3f seconds -> probably slow realtime virus scanner.", delayExtract);
|
||||||
qWarning("Please report performance problems to your anti-virus developer !!!\n");
|
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
|
//Register all translations
|
||||||
initTranslations();
|
initTranslations();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user