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:
parent
c3cfe577b0
commit
2ee08c5f4b
@ -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
|
||||
|
@ -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!)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,11 +109,17 @@ AbstractTool::AbstractTool(void)
|
||||
*/
|
||||
AbstractTool::~AbstractTool(void)
|
||||
{
|
||||
if(m_handle_jobObject)
|
||||
QMutexLocker lock(m_mutex_startProcess);
|
||||
|
||||
if(m_jobObjRefCount >= 1U)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user