mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 476346 - Spawner.exec() fails after incomplete process termination
This commit is contained in:
parent
d510c87df6
commit
0e382c064b
10 changed files with 55 additions and 30 deletions
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||||
Bundle-ManifestVersion: 2
|
Bundle-ManifestVersion: 2
|
||||||
Bundle-Name: %fragmentName.win32.x86
|
Bundle-Name: %fragmentName.win32.x86
|
||||||
Bundle-SymbolicName: org.eclipse.cdt.core.win32.x86;singleton:=true
|
Bundle-SymbolicName: org.eclipse.cdt.core.win32.x86;singleton:=true
|
||||||
Bundle-Version: 5.4.0.qualifier
|
Bundle-Version: 5.4.1.qualifier
|
||||||
Bundle-Vendor: %providerName
|
Bundle-Vendor: %providerName
|
||||||
Fragment-Host: org.eclipse.cdt.core.native;bundle-version="[5.7.0,6.0.0)"
|
Fragment-Host: org.eclipse.cdt.core.native;bundle-version="[5.7.0,6.0.0)"
|
||||||
Bundle-Localization: plugin
|
Bundle-Localization: plugin
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -11,7 +11,7 @@
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<version>5.4.0-SNAPSHOT</version>
|
<version>5.4.1-SNAPSHOT</version>
|
||||||
<artifactId>org.eclipse.cdt.core.win32.x86</artifactId>
|
<artifactId>org.eclipse.cdt.core.win32.x86</artifactId>
|
||||||
<packaging>eclipse-plugin</packaging>
|
<packaging>eclipse-plugin</packaging>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||||
Bundle-ManifestVersion: 2
|
Bundle-ManifestVersion: 2
|
||||||
Bundle-Name: %fragmentName.win32.x86_64
|
Bundle-Name: %fragmentName.win32.x86_64
|
||||||
Bundle-SymbolicName: org.eclipse.cdt.core.win32.x86_64;singleton:=true
|
Bundle-SymbolicName: org.eclipse.cdt.core.win32.x86_64;singleton:=true
|
||||||
Bundle-Version: 5.4.0.qualifier
|
Bundle-Version: 5.4.1.qualifier
|
||||||
Fragment-Host: org.eclipse.cdt.core.native;bundle-version="[5.7.0,6.0.0)"
|
Fragment-Host: org.eclipse.cdt.core.native;bundle-version="[5.7.0,6.0.0)"
|
||||||
Eclipse-PlatformFilter: (&(osgi.os=win32)(osgi.arch=x86_64))
|
Eclipse-PlatformFilter: (&(osgi.os=win32)(osgi.arch=x86_64))
|
||||||
Bundle-Vendor: %providerName
|
Bundle-Vendor: %providerName
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -11,7 +11,7 @@
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<version>5.4.0-SNAPSHOT</version>
|
<version>5.4.1-SNAPSHOT</version>
|
||||||
<artifactId>org.eclipse.cdt.core.win32.x86_64</artifactId>
|
<artifactId>org.eclipse.cdt.core.win32.x86_64</artifactId>
|
||||||
<packaging>eclipse-plugin</packaging>
|
<packaging>eclipse-plugin</packaging>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2002, 2011 QNX Software Systems and others.
|
* Copyright (c) 2002, 2015 QNX Software Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
#define PIPE_NAME_LENGTH 100 // Size of pipe name buffer
|
#define PIPE_NAME_LENGTH 100 // Size of pipe name buffer
|
||||||
#define PIPE_TIMEOUT 10000 // Default time-out value, in milliseconds.
|
#define PIPE_TIMEOUT 10000 // Default time-out value, in milliseconds.
|
||||||
|
|
||||||
#define MAX_PROCS (100) // Maximum number of simultaneiously runnig processes
|
#define MAX_PROCS (100) // Maximum number of simultaneously running processes
|
||||||
|
|
||||||
|
|
||||||
// Process description block. Should be created for each launched process
|
// Process description block. Should be created for each launched process
|
||||||
|
@ -53,7 +53,7 @@ static int procCounter = 0; // Number of running processes
|
||||||
// This is a VM helper
|
// This is a VM helper
|
||||||
void ThrowByName(JNIEnv *env, const char *name, const char *msg);
|
void ThrowByName(JNIEnv *env, const char *name, const char *msg);
|
||||||
|
|
||||||
// Creates _procInfo block for every launched procss
|
// Creates _procInfo block for every launched process
|
||||||
pProcInfo_t createProcInfo();
|
pProcInfo_t createProcInfo();
|
||||||
|
|
||||||
// Find process description for this pid
|
// Find process description for this pid
|
||||||
|
@ -62,7 +62,7 @@ pProcInfo_t findProcInfo(int pid);
|
||||||
// We launch separate thread for each project to trap it termination
|
// We launch separate thread for each project to trap it termination
|
||||||
void _cdecl waitProcTermination(void* pv) ;
|
void _cdecl waitProcTermination(void* pv) ;
|
||||||
|
|
||||||
// This is a helper function to prevent losing of quotatin marks
|
// This is a helper function to prevent losing of quotation marks
|
||||||
static int copyTo(wchar_t * target, const wchar_t * source, int cpyLenght, int availSpace);
|
static int copyTo(wchar_t * target, const wchar_t * source, int cpyLenght, int availSpace);
|
||||||
|
|
||||||
// Use this function to clean project descriptor and return it to the pool of available blocks.
|
// Use this function to clean project descriptor and return it to the pool of available blocks.
|
||||||
|
@ -89,7 +89,7 @@ static HMODULE hVM = NULL; // VM handler
|
||||||
|
|
||||||
static pProcInfo_t pInfo = NULL;
|
static pProcInfo_t pInfo = NULL;
|
||||||
|
|
||||||
static int nCounter = 0; // We use it to build unique synchronisation object names
|
static int nCounter = 0; // We use it to build unique synchronization object names
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Launcher; launchess process and traps its termination
|
// Launcher; launchess process and traps its termination
|
||||||
|
@ -148,7 +148,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
||||||
pProcInfo_t pCurProcInfo;
|
pProcInfo_t pCurProcInfo;
|
||||||
|
|
||||||
// This needs to be big enough to contain the name of the event used when calling CreateEventW bellow.
|
// This needs to be big enough to contain the name of the event used when calling CreateEventW bellow.
|
||||||
// It is made of a prefix (7 characters max) plus the value of a pointer that gets outputed in characters.
|
// It is made of a prefix (7 characters max) plus the value of a pointer that gets output in characters.
|
||||||
// This will be bigger in the case of 64 bit.
|
// This will be bigger in the case of 64 bit.
|
||||||
static const int MAX_EVENT_NAME_LENGTH = 50;
|
static const int MAX_EVENT_NAME_LENGTH = 50;
|
||||||
wchar_t eventBreakName[MAX_EVENT_NAME_LENGTH];
|
wchar_t eventBreakName[MAX_EVENT_NAME_LENGTH];
|
||||||
|
@ -224,13 +224,18 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct starter's command line
|
// Construct starter's command line
|
||||||
swprintf(eventBreakName, L"SABreak%p", pCurProcInfo);
|
swprintf(eventBreakName, L"SABreak%010i", nLocalCounter);
|
||||||
swprintf(eventWaitName, L"SAWait%p", pCurProcInfo);
|
swprintf(eventWaitName, L"SAWait%010i", nLocalCounter);
|
||||||
swprintf(eventTerminateName, L"SATerm%p", pCurProcInfo);
|
swprintf(eventTerminateName, L"SATerm%010i", nLocalCounter);
|
||||||
swprintf(eventKillName, L"SAKill%p", pCurProcInfo);
|
swprintf(eventKillName, L"SAKill%010i", nLocalCounter);
|
||||||
swprintf(eventCtrlcName, L"SACtrlc%p", pCurProcInfo);
|
swprintf(eventCtrlcName, L"SACtrlc%010i", nLocalCounter);
|
||||||
|
|
||||||
pCurProcInfo->eventBreak = CreateEventW(NULL, FALSE, FALSE, eventBreakName);
|
pCurProcInfo->eventBreak = CreateEventW(NULL, FALSE, FALSE, eventBreakName);
|
||||||
|
if(NULL == pCurProcInfo->eventBreak || GetLastError() == ERROR_ALREADY_EXISTS)
|
||||||
|
{
|
||||||
|
ThrowByName(env, "java/io/IOException", "Cannot create event");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
pCurProcInfo->eventWait = CreateEventW(NULL, TRUE, FALSE, eventWaitName);
|
pCurProcInfo->eventWait = CreateEventW(NULL, TRUE, FALSE, eventWaitName);
|
||||||
pCurProcInfo->eventTerminate = CreateEventW(NULL, FALSE, FALSE, eventTerminateName);
|
pCurProcInfo->eventTerminate = CreateEventW(NULL, FALSE, FALSE, eventTerminateName);
|
||||||
pCurProcInfo->eventKill = CreateEventW(NULL, FALSE, FALSE, eventKillName);
|
pCurProcInfo->eventKill = CreateEventW(NULL, FALSE, FALSE, eventKillName);
|
||||||
|
@ -687,7 +692,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise
|
||||||
#endif
|
#endif
|
||||||
SetEvent(pCurProcInfo -> eventTerminate);
|
SetEvent(pCurProcInfo -> eventTerminate);
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR
|
||||||
OutputDebugStringW(_T("Spawner signalled TERM event\n"));
|
OutputDebugStringW(_T("Spawner signaled TERM event\n"));
|
||||||
#endif
|
#endif
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -700,7 +705,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise
|
||||||
#endif
|
#endif
|
||||||
SetEvent(pCurProcInfo -> eventKill);
|
SetEvent(pCurProcInfo -> eventKill);
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR
|
||||||
OutputDebugStringW(_T("Spawner signalled KILL event\n"));
|
OutputDebugStringW(_T("Spawner signaled KILL event\n"));
|
||||||
#endif
|
#endif
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -886,10 +891,10 @@ void cleanUpProcBlock(pProcInfo_t pCurProcInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Running in separae thread and waiting for the process termination
|
// Running in separate thread and waiting for the process termination
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// pv - (int)pv is a pid
|
// pv - pointer to PROCESS_INFORMATION struct
|
||||||
// Return : always 0
|
// Return : no
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
void _cdecl waitProcTermination(void* pv)
|
void _cdecl waitProcTermination(void* pv)
|
||||||
{
|
{
|
||||||
|
@ -909,8 +914,7 @@ void _cdecl waitProcTermination(void* pv)
|
||||||
cleanUpProcBlock(pInfo + i);
|
cleanUpProcBlock(pInfo + i);
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR
|
||||||
swprintf(buffer, _T("waitProcTermination: set PID %i to 0\n"),
|
swprintf(buffer, _T("waitProcTermination: set PID %i to 0\n"),
|
||||||
pInfo[i].pid,
|
pi->dwProcessId);
|
||||||
GetLastError());
|
|
||||||
OutputDebugStringW(buffer);
|
OutputDebugStringW(buffer);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -953,12 +957,12 @@ int copyTo(wchar_t * target, const wchar_t * source, int cpyLength, int availSpa
|
||||||
else
|
else
|
||||||
if(wcschr(source, _T(' ')) == NULL)
|
if(wcschr(source, _T(' ')) == NULL)
|
||||||
{
|
{
|
||||||
// No reason to quotate term becase it doesn't have embedded spaces
|
// No reason to quote term because it doesn't have embedded spaces
|
||||||
nQuotationMode = QUOTATION_NONE;
|
nQuotationMode = QUOTATION_NONE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Needs to be quotated
|
// Needs to be quoted
|
||||||
nQuotationMode = QUOTATION_DO;
|
nQuotationMode = QUOTATION_DO;
|
||||||
*target = _T('\"');
|
*target = _T('\"');
|
||||||
++j;
|
++j;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2002, 2010 QNX Software Systems and others.
|
* Copyright (c) 2002, 2015 QNX Software Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -252,7 +252,7 @@ int main() {
|
||||||
return -1;;
|
return -1;;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR_DETAILS
|
||||||
wchar_t * lpvEnv = GetEnvironmentStringsW();
|
wchar_t * lpvEnv = GetEnvironmentStringsW();
|
||||||
|
|
||||||
// If the returned pointer is NULL, exit.
|
// If the returned pointer is NULL, exit.
|
||||||
|
@ -277,10 +277,31 @@ int main() {
|
||||||
#endif
|
#endif
|
||||||
// Create job object
|
// Create job object
|
||||||
HANDLE hJob = CreateJobObject(NULL, NULL);
|
HANDLE hJob = CreateJobObject(NULL, NULL);
|
||||||
|
if (hJob != NULL) {
|
||||||
|
// Configure job to
|
||||||
|
// - terminate all associated processes when the last handle to it is closed
|
||||||
|
// - allow child processes to break away from the job.
|
||||||
|
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo;
|
||||||
|
ZeroMemory(&jobInfo, sizeof(jobInfo));
|
||||||
|
jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK;
|
||||||
|
if (!SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jobInfo, sizeof(jobInfo))) {
|
||||||
|
#ifdef DEBUG_MONITOR
|
||||||
|
OutputDebugStringW(_T("Cannot set job information\n"));
|
||||||
|
DisplayErrorMessage();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef DEBUG_MONITOR
|
||||||
|
OutputDebugStringW(_T("Cannot create job object\n"));
|
||||||
|
DisplayErrorMessage();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
// Spawn the other processes as part of this Process Group
|
// Spawn the other processes as part of this Process Group
|
||||||
|
// If this process is already part of a job, the flag CREATE_BREAKAWAY_FROM_JOB
|
||||||
|
// makes the child process detach from the job, such that we can assign it
|
||||||
|
// to our own job object.
|
||||||
BOOL f = CreateProcessW(NULL, szCmdLine, NULL, NULL, TRUE,
|
BOOL f = CreateProcessW(NULL, szCmdLine, NULL, NULL, TRUE,
|
||||||
0, NULL, NULL, &si, &pi);
|
CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi);
|
||||||
|
|
||||||
// We don't need them any more
|
// We don't need them any more
|
||||||
CloseHandle(stdHandles[0]);
|
CloseHandle(stdHandles[0]);
|
||||||
|
@ -292,7 +313,7 @@ int main() {
|
||||||
swprintf(buffer, _T("Process %i started\n"), pi.dwProcessId);
|
swprintf(buffer, _T("Process %i started\n"), pi.dwProcessId);
|
||||||
OutputDebugStringW(buffer);
|
OutputDebugStringW(buffer);
|
||||||
#endif
|
#endif
|
||||||
SetEvent(waitEvent); // Means thar process has been spawned
|
SetEvent(waitEvent); // Means that process has been spawned
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
h[1] = pi.hProcess;
|
h[1] = pi.hProcess;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue