Fixed a regression in d92fb7fbcc: We must not close the handle to the Job Object, as long as there still might be a process "tool" running. The regression caused child processes to be terminated unexpectedly sometimes! We now use reference counting in order to avoid this problem.

This commit is contained in:
LoRd_MuldeR 2012-03-01 02:45:21 +01:00
parent c3cfe577b0
commit 2ee08c5f4b
5 changed files with 74 additions and 20 deletions

View File

@ -826,18 +826,20 @@ LameXP is developed using the <a href="http://en.wikipedia.org/wiki/Git_(softwar
<br>
LameXP is currently being developed using the following build environment:<br><ul>
<li><a href="http://www.microsoft.com/visualstudio/en-us" target="_blank">Visual Studio 2010</a> with Service Pack 1, running on Windows 7 with Service Pack 1
<li>Desktop Qt v4.7.3 (MSVC 2008), included in <a href="http://qt.nokia.com/products/qt-sdk" target="_blank">Qt SDK v1.1</a>
<li>Desktop Qt v4.8.0 (MSVC 2010), included in <a href="http://qt.nokia.com/products/qt-sdk" target="_blank">Qt SDK v1.2</a>
<li><a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=35AEDA01-421D-4BA5-B44B-543DC8C33A20" target="_blank">Windows Platform SDK v7.1</a> (Windows SDK for Windows 7 and .NET Framework 4)
<li>The minimum supported Windows version is Windows XP with Service Pack 2</ul>
<li>The minimum supported build platform is Windows XP with Service Pack 2</ul>
<br>
Also note the following hints:<br><ul>
<li>Run "qtenv2.bat" before launching Visual Studio in order to set up the Qt environment
<li>Visual Studio 2008 solution/project files are still provided for people targeting Windows 2000
<li>In order to make a "fully static" build of LameXP, you need to compile Qt as 'static' libraries
<li>The Windows Platform SDK v6.0A should work as well, but there may be a few limitations
<li>Only the "fully static" builds may still run on Windows 2000, due to workarounds we implemented
<li>Support for the GNU Toolchain (GCC/MinGW + Make) is planned for a future version</ul>
<br>
In order to use the LameXP deployment scripts you need the following tools:<br><ul>
<li>Visual Studio 2010 with Service Pack 1 with Desktop Qt v4.8.0
<li><a href="http://www.7-zip.org/" target="_blank">7-Zip</a> - file archiver with a high compression ratio
<li><a href="http://www.scratchpaper.com/" target="_blank">NSIS</a> - Nullsoft Scriptable Install System (Unicode Version)<ul>
<li><a href="http://nsis.sourceforge.net/StdUtils_plug-in" target="_blank">StdUtils plug-in</a>
@ -847,7 +849,7 @@ In order to use the LameXP deployment scripts you need the following tools:<br><
<li><a href="http://upx.sourceforge.net/" target="_blank">UPX</a> - the Ultimate Packer for eXecutables
<li><a href="http://www.matcode.com/mpress.htm" target="_blank">MPRESS</a> - high-performance executable packer for PE32/PE32+
<li><a href="ftp://ftp.gnupg.org/gcrypt/binary/" target="_blank">GnuPG</a> - the GNU Privacy Guard v1.4.x<div style="height:7px"></div>
<li>Copy 'buildenv.template.txt' to 'buildenv.txt' and edit the paths as needed!</ul>
<li>NOTE: Copy 'buildenv.template.txt' to 'buildenv.txt' and edit the paths as needed!</ul>
<br>
Instructions to build Qt as 'static' libraries:<br><ul>
<li>Make sure Visual Studio 2010 and Strawberry Perl for Windows are installed

View File

@ -30,7 +30,7 @@
#define VER_LAMEXP_MINOR_LO 4
#define VER_LAMEXP_TYPE Beta
#define VER_LAMEXP_PATCH 3
#define VER_LAMEXP_BUILD 894
#define VER_LAMEXP_BUILD 897
///////////////////////////////////////////////////////////////////////////////
// Tool versions (minimum expected versions!)

View File

@ -110,7 +110,7 @@ void SplashScreen::showSplash(QThread *thread)
{
opacity = 0.01 * static_cast<double>(i);
splashScreen->setWindowOpacity(opacity);
QApplication::processEvents();
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, FADE_DELAY);
Sleep(FADE_DELAY);
}
@ -135,7 +135,7 @@ void SplashScreen::showSplash(QThread *thread)
{
opacity = 0.01 * static_cast<double>(i);
splashScreen->setWindowOpacity(opacity);
QApplication::processEvents();
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, FADE_DELAY);
Sleep(FADE_DELAY);
}

View File

@ -40,8 +40,16 @@ typedef BOOL (WINAPI *AssignProcessToJobObjectFun)(__in HANDLE hJob, __in HANDLE
/*
* Static vars
*/
quint64 AbstractTool::m_lastLaunchTime = 0ui64;
QMutex *AbstractTool::m_mutex_startProcess = NULL;
HANDLE AbstractTool::m_handle_jobObject = NULL;
unsigned int AbstractTool::m_jobObjRefCount = 0U;
/*
* Const
*/
static const DWORD START_DELAY = 333; //in milliseconds
static const quint64 START_DELAY_NANO = START_DELAY * 1000 * 10; //in 100-nanosecond intervals
/*
* Constructor
@ -56,7 +64,9 @@ AbstractTool::AbstractTool(void)
m_mutex_startProcess = new QMutex();
}
if(!m_handle_jobObject)
QMutexLocker lock(m_mutex_startProcess);
if(m_jobObjRefCount < 1U)
{
if(!CreateJobObjectPtr || !SetInformationJobObjectPtr)
{
@ -66,20 +76,30 @@ AbstractTool::AbstractTool(void)
}
if(CreateJobObjectPtr && SetInformationJobObjectPtr)
{
m_handle_jobObject = CreateJobObjectPtr(NULL, NULL);
if(m_handle_jobObject == INVALID_HANDLE_VALUE)
{
m_handle_jobObject = NULL;
}
if(m_handle_jobObject)
HANDLE jobObject = CreateJobObjectPtr(NULL, NULL);
if((jobObject != NULL) && (jobObject != INVALID_HANDLE_VALUE))
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
memset(&jobExtendedLimitInfo.BasicLimitInformation, 0, sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION));
jobExtendedLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
SetInformationJobObjectPtr(m_handle_jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
if(SetInformationJobObjectPtr(jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)))
{
m_handle_jobObject = jobObject;
m_jobObjRefCount = 1U;
}
else
{
qWarning("Failed to set job object information!");
CloseHandle(jobObject);
}
}
}
}
else
{
m_jobObjRefCount++;
}
m_firstLaunch = true;
}
@ -89,10 +109,16 @@ AbstractTool::AbstractTool(void)
*/
AbstractTool::~AbstractTool(void)
{
if(m_handle_jobObject)
QMutexLocker lock(m_mutex_startProcess);
if(m_jobObjRefCount >= 1U)
{
CloseHandle(m_handle_jobObject);
m_handle_jobObject = NULL;
m_jobObjRefCount--;
if((m_jobObjRefCount < 1U) && m_handle_jobObject)
{
CloseHandle(m_handle_jobObject);
m_handle_jobObject = NULL;
}
}
}
@ -104,6 +130,12 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
static AssignProcessToJobObjectFun AssignProcessToJobObjectPtr = NULL;
QMutexLocker lock(m_mutex_startProcess);
if(currentTime() <= m_lastLaunchTime)
{
Sleep(START_DELAY);
}
emit messageLogged(commandline2string(program, args) + "\n");
QProcessEnvironment env = process.processEnvironment();
@ -124,10 +156,12 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
if(process.waitForStarted())
{
if(AssignProcessToJobObjectPtr)
if(AssignProcessToJobObjectPtr && m_handle_jobObject)
{
AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess);
if(!AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess))
{
qWarning("Failed to assign process to job object!");
}
}
if(!SetPriorityClass(process.pid()->hProcess, BELOW_NORMAL_PRIORITY_CLASS))
{
@ -142,6 +176,7 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
m_firstLaunch = false;
}
m_lastLaunchTime = currentTime() + START_DELAY_NANO;
return true;
}
@ -151,6 +186,8 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
process.kill();
process.waitForFinished(-1);
m_lastLaunchTime = currentTime() + START_DELAY_NANO;
return false;
}
@ -193,3 +230,14 @@ QString AbstractTool::pathToShort(const QString &longPath)
return (shortPath.isEmpty() ? longPath : shortPath);
}
const quint64 AbstractTool::currentTime(void)
{
FILETIME fileTime;
GetSystemTimeAsFileTime(&fileTime);
ULARGE_INTEGER temp;
temp.HighPart = fileTime.dwHighDateTime;
temp.LowPart = fileTime.dwLowDateTime;
return temp.QuadPart;
}

View File

@ -37,6 +37,7 @@ public:
bool startProcess(QProcess &process, const QString &program, const QStringList &args);
static QString commandline2string(const QString &program, const QStringList &arguments);
static QString AbstractTool::pathToShort(const QString &longPath);
static inline const quint64 currentTime(void);
signals:
void statusUpdated(int progress);
@ -46,7 +47,10 @@ protected:
static const int m_processTimeoutInterval = 600000;
private:
static quint64 m_lastLaunchTime;
static QMutex *m_mutex_startProcess;
static unsigned int m_jobObjRefCount;
static void *m_handle_jobObject;
bool m_firstLaunch;
};