Fixed a regression in d92fb7fbcc34b7bf6b1649befab1d9eafec13684: 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>
|
<br>
|
||||||
LameXP is currently being developed using the following build environment:<br><ul>
|
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><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><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>
|
<br>
|
||||||
Also note the following hints:<br><ul>
|
Also note the following hints:<br><ul>
|
||||||
<li>Run "qtenv2.bat" before launching Visual Studio in order to set up the Qt environment
|
<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>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>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>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>
|
<li>Support for the GNU Toolchain (GCC/MinGW + Make) is planned for a future version</ul>
|
||||||
<br>
|
<br>
|
||||||
In order to use the LameXP deployment scripts you need the following tools:<br><ul>
|
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.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://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>
|
<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://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="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><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>
|
<br>
|
||||||
Instructions to build Qt as 'static' libraries:<br><ul>
|
Instructions to build Qt as 'static' libraries:<br><ul>
|
||||||
<li>Make sure Visual Studio 2010 and Strawberry Perl for Windows are installed
|
<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_MINOR_LO 4
|
||||||
#define VER_LAMEXP_TYPE Beta
|
#define VER_LAMEXP_TYPE Beta
|
||||||
#define VER_LAMEXP_PATCH 3
|
#define VER_LAMEXP_PATCH 3
|
||||||
#define VER_LAMEXP_BUILD 894
|
#define VER_LAMEXP_BUILD 897
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Tool versions (minimum expected versions!)
|
// Tool versions (minimum expected versions!)
|
||||||
|
@ -110,7 +110,7 @@ void SplashScreen::showSplash(QThread *thread)
|
|||||||
{
|
{
|
||||||
opacity = 0.01 * static_cast<double>(i);
|
opacity = 0.01 * static_cast<double>(i);
|
||||||
splashScreen->setWindowOpacity(opacity);
|
splashScreen->setWindowOpacity(opacity);
|
||||||
QApplication::processEvents();
|
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, FADE_DELAY);
|
||||||
Sleep(FADE_DELAY);
|
Sleep(FADE_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ void SplashScreen::showSplash(QThread *thread)
|
|||||||
{
|
{
|
||||||
opacity = 0.01 * static_cast<double>(i);
|
opacity = 0.01 * static_cast<double>(i);
|
||||||
splashScreen->setWindowOpacity(opacity);
|
splashScreen->setWindowOpacity(opacity);
|
||||||
QApplication::processEvents();
|
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, FADE_DELAY);
|
||||||
Sleep(FADE_DELAY);
|
Sleep(FADE_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,16 @@ typedef BOOL (WINAPI *AssignProcessToJobObjectFun)(__in HANDLE hJob, __in HANDLE
|
|||||||
/*
|
/*
|
||||||
* Static vars
|
* Static vars
|
||||||
*/
|
*/
|
||||||
|
quint64 AbstractTool::m_lastLaunchTime = 0ui64;
|
||||||
QMutex *AbstractTool::m_mutex_startProcess = NULL;
|
QMutex *AbstractTool::m_mutex_startProcess = NULL;
|
||||||
HANDLE AbstractTool::m_handle_jobObject = 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
|
* Constructor
|
||||||
@ -56,7 +64,9 @@ AbstractTool::AbstractTool(void)
|
|||||||
m_mutex_startProcess = new QMutex();
|
m_mutex_startProcess = new QMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!m_handle_jobObject)
|
QMutexLocker lock(m_mutex_startProcess);
|
||||||
|
|
||||||
|
if(m_jobObjRefCount < 1U)
|
||||||
{
|
{
|
||||||
if(!CreateJobObjectPtr || !SetInformationJobObjectPtr)
|
if(!CreateJobObjectPtr || !SetInformationJobObjectPtr)
|
||||||
{
|
{
|
||||||
@ -66,20 +76,30 @@ AbstractTool::AbstractTool(void)
|
|||||||
}
|
}
|
||||||
if(CreateJobObjectPtr && SetInformationJobObjectPtr)
|
if(CreateJobObjectPtr && SetInformationJobObjectPtr)
|
||||||
{
|
{
|
||||||
m_handle_jobObject = CreateJobObjectPtr(NULL, NULL);
|
HANDLE jobObject = CreateJobObjectPtr(NULL, NULL);
|
||||||
if(m_handle_jobObject == INVALID_HANDLE_VALUE)
|
if((jobObject != NULL) && (jobObject != INVALID_HANDLE_VALUE))
|
||||||
{
|
|
||||||
m_handle_jobObject = NULL;
|
|
||||||
}
|
|
||||||
if(m_handle_jobObject)
|
|
||||||
{
|
{
|
||||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
|
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
|
||||||
memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
|
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;
|
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;
|
m_firstLaunch = true;
|
||||||
}
|
}
|
||||||
@ -89,10 +109,16 @@ AbstractTool::AbstractTool(void)
|
|||||||
*/
|
*/
|
||||||
AbstractTool::~AbstractTool(void)
|
AbstractTool::~AbstractTool(void)
|
||||||
{
|
{
|
||||||
if(m_handle_jobObject)
|
QMutexLocker lock(m_mutex_startProcess);
|
||||||
|
|
||||||
|
if(m_jobObjRefCount >= 1U)
|
||||||
{
|
{
|
||||||
CloseHandle(m_handle_jobObject);
|
m_jobObjRefCount--;
|
||||||
m_handle_jobObject = NULL;
|
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;
|
static AssignProcessToJobObjectFun AssignProcessToJobObjectPtr = NULL;
|
||||||
|
|
||||||
QMutexLocker lock(m_mutex_startProcess);
|
QMutexLocker lock(m_mutex_startProcess);
|
||||||
|
|
||||||
|
if(currentTime() <= m_lastLaunchTime)
|
||||||
|
{
|
||||||
|
Sleep(START_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
emit messageLogged(commandline2string(program, args) + "\n");
|
emit messageLogged(commandline2string(program, args) + "\n");
|
||||||
|
|
||||||
QProcessEnvironment env = process.processEnvironment();
|
QProcessEnvironment env = process.processEnvironment();
|
||||||
@ -124,10 +156,12 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
|
|||||||
|
|
||||||
if(process.waitForStarted())
|
if(process.waitForStarted())
|
||||||
{
|
{
|
||||||
|
if(AssignProcessToJobObjectPtr && m_handle_jobObject)
|
||||||
if(AssignProcessToJobObjectPtr)
|
|
||||||
{
|
{
|
||||||
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))
|
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_firstLaunch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_lastLaunchTime = currentTime() + START_DELAY_NANO;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +186,8 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
|
|||||||
|
|
||||||
process.kill();
|
process.kill();
|
||||||
process.waitForFinished(-1);
|
process.waitForFinished(-1);
|
||||||
|
|
||||||
|
m_lastLaunchTime = currentTime() + START_DELAY_NANO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,3 +230,14 @@ QString AbstractTool::pathToShort(const QString &longPath)
|
|||||||
return (shortPath.isEmpty() ? longPath : shortPath);
|
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);
|
bool startProcess(QProcess &process, const QString &program, const QStringList &args);
|
||||||
static QString commandline2string(const QString &program, const QStringList &arguments);
|
static QString commandline2string(const QString &program, const QStringList &arguments);
|
||||||
static QString AbstractTool::pathToShort(const QString &longPath);
|
static QString AbstractTool::pathToShort(const QString &longPath);
|
||||||
|
static inline const quint64 currentTime(void);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void statusUpdated(int progress);
|
void statusUpdated(int progress);
|
||||||
@ -46,7 +47,10 @@ protected:
|
|||||||
static const int m_processTimeoutInterval = 600000;
|
static const int m_processTimeoutInterval = 600000;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static quint64 m_lastLaunchTime;
|
||||||
static QMutex *m_mutex_startProcess;
|
static QMutex *m_mutex_startProcess;
|
||||||
|
static unsigned int m_jobObjRefCount;
|
||||||
static void *m_handle_jobObject;
|
static void *m_handle_jobObject;
|
||||||
|
|
||||||
bool m_firstLaunch;
|
bool m_firstLaunch;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user