mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-02 05:45:58 +02:00
Fixed:
282735 - starter.exe can end up rapid-firing CTRL-C's to process that won't die 282736 - starter.exe should support SIGKILL
This commit is contained in:
parent
3cdfd7abfa
commit
cb443c104d
4 changed files with 61 additions and 28 deletions
|
@ -39,10 +39,11 @@ typedef struct _procInfo {
|
||||||
int uid; // quasi-unique process ID; we have to create it to avoid duplicated pid
|
int uid; // quasi-unique process ID; we have to create it to avoid duplicated pid
|
||||||
// (actually this impossible from OS point of view but it is still possible
|
// (actually this impossible from OS point of view but it is still possible
|
||||||
// a clash of new created and already finished process with one and the same PID.
|
// a clash of new created and already finished process with one and the same PID.
|
||||||
// 3 events connected to this process (see starter)
|
// 4 events connected to this process (see starter)
|
||||||
HANDLE eventBreak;
|
HANDLE eventBreak; // signaled when Spawner.interrupt() is called; mildest of the terminate requests (SIGINT signal in UNIX world)
|
||||||
HANDLE eventWait;
|
HANDLE eventWait;
|
||||||
HANDLE eventTerminate;
|
HANDLE eventTerminate; // signaled when Spawner.terminate() is called; more forceful terminate request (SIGTERM signal in UNIX world)
|
||||||
|
HANDLE eventKill; // signaled when Spawner.kill() is called; most forceful terminate request (SIGKILL signal in UNIX world)
|
||||||
} procInfo_t, * pProcInfo_t;
|
} procInfo_t, * pProcInfo_t;
|
||||||
|
|
||||||
static int procCounter = 0; // Number of running processes
|
static int procCounter = 0; // Number of running processes
|
||||||
|
@ -146,6 +147,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
||||||
wchar_t eventBreakName[20];
|
wchar_t eventBreakName[20];
|
||||||
wchar_t eventWaitName[20];
|
wchar_t eventWaitName[20];
|
||||||
wchar_t eventTerminateName[20];
|
wchar_t eventTerminateName[20];
|
||||||
|
wchar_t eventKillName[20];
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR
|
||||||
wchar_t buffer[1000];
|
wchar_t buffer[1000];
|
||||||
#endif
|
#endif
|
||||||
|
@ -217,14 +219,14 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
||||||
swprintf(eventBreakName, L"SABreak%p", pCurProcInfo);
|
swprintf(eventBreakName, L"SABreak%p", pCurProcInfo);
|
||||||
swprintf(eventWaitName, L"SAWait%p", pCurProcInfo);
|
swprintf(eventWaitName, L"SAWait%p", pCurProcInfo);
|
||||||
swprintf(eventTerminateName, L"SATerm%p", pCurProcInfo);
|
swprintf(eventTerminateName, L"SATerm%p", pCurProcInfo);
|
||||||
pCurProcInfo -> eventBreak = CreateEventW(NULL, TRUE, FALSE, eventBreakName);
|
swprintf(eventKillName, L"SAKill%p", pCurProcInfo);
|
||||||
ResetEvent(pCurProcInfo -> eventBreak);
|
|
||||||
pCurProcInfo -> eventWait = CreateEventW(NULL, TRUE, FALSE, eventWaitName);
|
|
||||||
ResetEvent(pCurProcInfo -> eventWait);
|
|
||||||
pCurProcInfo -> eventTerminate = CreateEventW(NULL, TRUE, FALSE, eventTerminateName);
|
|
||||||
ResetEvent(pCurProcInfo -> eventTerminate);
|
|
||||||
|
|
||||||
swprintf(szCmdLine, L"\"%sstarter.exe\" %i %i %s %s %s ", path, pid, nLocalCounter, eventBreakName, eventWaitName, eventTerminateName);
|
pCurProcInfo->eventBreak = CreateEventW(NULL, TRUE, FALSE, eventBreakName);
|
||||||
|
pCurProcInfo->eventWait = CreateEventW(NULL, TRUE, FALSE, eventWaitName);
|
||||||
|
pCurProcInfo->eventTerminate = CreateEventW(NULL, FALSE, FALSE, eventTerminateName);
|
||||||
|
pCurProcInfo->eventKill = CreateEventW(NULL, FALSE, FALSE, eventKillName);
|
||||||
|
|
||||||
|
swprintf(szCmdLine, L"\"%sstarter.exe\" %i %i %s %s %s %s ", path, pid, nLocalCounter, eventBreakName, eventWaitName, eventTerminateName, eventKillName);
|
||||||
nPos = wcslen(szCmdLine);
|
nPos = wcslen(szCmdLine);
|
||||||
|
|
||||||
// Prepare command line
|
// Prepare command line
|
||||||
|
@ -667,14 +669,26 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise
|
||||||
// Temporary do nothing
|
// Temporary do nothing
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
case SIG_KILL:
|
|
||||||
case SIG_TERM:
|
case SIG_TERM:
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR
|
||||||
swprintf(buffer, _T("Spawner received KILL or TERM signal for process %i\n"),
|
swprintf(buffer, _T("Spawner received TERM signal for process %i\n"),
|
||||||
pCurProcInfo -> pid);
|
pCurProcInfo -> pid);
|
||||||
OutputDebugStringW(buffer);
|
OutputDebugStringW(buffer);
|
||||||
#endif
|
#endif
|
||||||
SetEvent(pCurProcInfo -> eventTerminate);
|
SetEvent(pCurProcInfo -> eventTerminate);
|
||||||
|
#ifdef DEBUG_MONITOR
|
||||||
|
OutputDebugStringW(_T("Spawner signalled TERM event\n"));
|
||||||
|
#endif
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIG_KILL:
|
||||||
|
#ifdef DEBUG_MONITOR
|
||||||
|
swprintf(buffer, _T("Spawner received KILL signal for process %i\n"),
|
||||||
|
pCurProcInfo -> pid);
|
||||||
|
OutputDebugStringW(buffer);
|
||||||
|
#endif
|
||||||
|
SetEvent(pCurProcInfo -> eventKill);
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR
|
||||||
OutputDebugStringW(_T("Spawner signalled KILL event\n"));
|
OutputDebugStringW(_T("Spawner signalled KILL event\n"));
|
||||||
#endif
|
#endif
|
||||||
|
@ -841,6 +855,12 @@ void cleanUpProcBlock(pProcInfo_t pCurProcInfo)
|
||||||
pCurProcInfo -> eventTerminate = 0;
|
pCurProcInfo -> eventTerminate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(0 != pCurProcInfo -> eventKill)
|
||||||
|
{
|
||||||
|
CloseHandle(pCurProcInfo -> eventKill);
|
||||||
|
pCurProcInfo -> eventKill = 0;
|
||||||
|
}
|
||||||
|
|
||||||
pCurProcInfo -> pid = 0;
|
pCurProcInfo -> pid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,8 +139,8 @@ int main() {
|
||||||
wchar_t ** argv = CommandLineToArgvW(GetCommandLine(), &argc);
|
wchar_t ** argv = CommandLineToArgvW(GetCommandLine(), &argc);
|
||||||
|
|
||||||
// Make sure that we've been passed the right number of arguments
|
// Make sure that we've been passed the right number of arguments
|
||||||
if (argc < 7) {
|
if (argc < 8) {
|
||||||
_tprintf(_T("Usage: %s (Three InheritableEventHandles) (CommandLineToSpawn)\n"),
|
_tprintf(_T("Usage: %s (four inheritable event handles) (CommandLineToSpawn)\n"),
|
||||||
argv[0]);
|
argv[0]);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ int main() {
|
||||||
szCmdLine[0]= 0;
|
szCmdLine[0]= 0;
|
||||||
int nPos = 0;
|
int nPos = 0;
|
||||||
|
|
||||||
for(int i = 6; i < argc; ++i)
|
for(int i = 7; i < argc; ++i)
|
||||||
{
|
{
|
||||||
int nCpyLen;
|
int nCpyLen;
|
||||||
int len= wcslen(argv[i]);
|
int len= wcslen(argv[i]);
|
||||||
|
@ -192,9 +192,11 @@ int main() {
|
||||||
|
|
||||||
BOOL exitProc = FALSE;
|
BOOL exitProc = FALSE;
|
||||||
HANDLE waitEvent = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[4]);
|
HANDLE waitEvent = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[4]);
|
||||||
HANDLE h[3];
|
HANDLE h[4];
|
||||||
h[0] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[3]);
|
h[0] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[3]); // simulated SIGINT
|
||||||
h[2] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[5]); // This is a terminate event
|
// h[1] we reserve for the process handle
|
||||||
|
h[2] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[5]); // simulated SIGTERM
|
||||||
|
h[3] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[6]); // simulated SIGKILL
|
||||||
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
|
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
|
||||||
|
|
||||||
int parentPid = wcstol(argv[1], NULL, 10);
|
int parentPid = wcstol(argv[1], NULL, 10);
|
||||||
|
@ -306,9 +308,10 @@ int main() {
|
||||||
{
|
{
|
||||||
// Wait for the spawned-process to die or for the event
|
// Wait for the spawned-process to die or for the event
|
||||||
// indicating that the processes should be forcibly killed.
|
// indicating that the processes should be forcibly killed.
|
||||||
switch (WaitForMultipleObjects(3, h, FALSE, INFINITE))
|
DWORD event = WaitForMultipleObjects(4, h, FALSE, INFINITE);
|
||||||
|
switch (event)
|
||||||
{
|
{
|
||||||
case WAIT_OBJECT_0 + 0: // Send Ctrl-C
|
case WAIT_OBJECT_0 + 0: // SIGINT
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR
|
||||||
swprintf(buffer, _T("starter (PID %i) received CTRL-C event\n"), currentPID);
|
swprintf(buffer, _T("starter (PID %i) received CTRL-C event\n"), currentPID);
|
||||||
OutputDebugStringW(buffer);
|
OutputDebugStringW(buffer);
|
||||||
|
@ -339,15 +342,22 @@ int main() {
|
||||||
exitProc = TRUE;
|
exitProc = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WAIT_OBJECT_0 + 2: // Kill
|
// Terminate and Kill behavior differ only for cygwin processes, where
|
||||||
|
// we use the cygwin 'kill' command. We send a SIGKILL in one case,
|
||||||
|
// SIGTERM in the other. For non-cygwin processes, both requests
|
||||||
|
// are treated exactly the same
|
||||||
|
case WAIT_OBJECT_0 + 2: // TERM
|
||||||
|
case WAIT_OBJECT_0 + 3: // KILL
|
||||||
|
{
|
||||||
|
const wchar_t* signal = (event == WAIT_OBJECT_0 + 2) ? L"TERM" : L"KILL";
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR
|
||||||
swprintf(buffer, _T("starter received KILL event (PID %i)\n"), currentPID);
|
swprintf(buffer, _T("starter received %s event (PID %i)\n"), signal, currentPID);
|
||||||
OutputDebugStringW(buffer);
|
OutputDebugStringW(buffer);
|
||||||
#endif
|
#endif
|
||||||
if (isCygwin(h[1])) {
|
if (isCygwin(h[1])) {
|
||||||
// Need to issue a kill command
|
// Need to issue a kill command
|
||||||
wchar_t kill[1024];
|
wchar_t kill[1024];
|
||||||
swprintf(kill, L"kill -SIGTERM %d", pi.dwProcessId);
|
swprintf(kill, L"kill -SIG%s %d", signal, pi.dwProcessId);
|
||||||
if (!runCygwinCommand(kill)) {
|
if (!runCygwinCommand(kill)) {
|
||||||
// fall back to console event
|
// fall back to console event
|
||||||
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
|
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
|
||||||
|
@ -365,10 +375,13 @@ int main() {
|
||||||
DisplayErrorMessage();
|
DisplayErrorMessage();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
exitProc = TRUE;
|
|
||||||
|
// Note that we keep trucking until the child process terminates (case WAIT_OBJECT_0 + 1)
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
// Unexpected code
|
// Unexpected code
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR
|
||||||
DisplayErrorMessage();
|
DisplayErrorMessage();
|
||||||
|
@ -378,7 +391,6 @@ int main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef DEBUG_MONITOR
|
#ifdef DEBUG_MONITOR
|
||||||
swprintf(buffer, _T("Cannot start: %s\n"), szCmdLine);
|
swprintf(buffer, _T("Cannot start: %s\n"), szCmdLine);
|
||||||
|
@ -397,6 +409,7 @@ int main() {
|
||||||
CloseHandle(h[0]);
|
CloseHandle(h[0]);
|
||||||
CloseHandle(h[1]);
|
CloseHandle(h[1]);
|
||||||
CloseHandle(h[2]);
|
CloseHandle(h[2]);
|
||||||
|
CloseHandle(h[3]);
|
||||||
|
|
||||||
return(dwExitCode);
|
return(dwExitCode);
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Add table
Reference in a new issue