1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 02:06:01 +02:00

Bug 568079: Hook into Eclipse tracing system for native code

After loading the spawner library, call the native method
configureNativeTrace() that will query the Eclipse platform for several
debug option strings.

Change-Id: I031bb2cdc04ba2675913b3b2e320039c28139638
Signed-off-by: Torbjörn Svensson <azoff@svenskalinuxforeningen.se>
This commit is contained in:
Torbjörn Svensson 2020-11-03 21:06:42 +01:00 committed by Jonah Graham
parent 09b1f93e7e
commit 1d2946184a
18 changed files with 187 additions and 121 deletions

View file

@ -1,4 +1,9 @@
org.eclipse.cdt.core.native/debug=false org.eclipse.cdt.core.native/debug=false
org.eclipse.cdt.core.native/debug/spawner=false
org.eclipse.cdt.core.native/debug/spawner/details=false
org.eclipse.cdt.core.native/debug/spawner/starter=false
org.eclipse.cdt.core.native/debug/spawner/read_report=false
# Used by org.eclipse.cdt.core.win32 fragment # Used by org.eclipse.cdt.core.win32 fragment
org.eclipse.cdt.core.native/debug/win32/registry=false org.eclipse.cdt.core.native/debug/win32/registry=false

View file

@ -47,6 +47,14 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise(JNIEnv *
*/ */
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor(JNIEnv *, jobject, jint); JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor(JNIEnv *, jobject, jint);
/*
* Class: org_eclipse_cdt_utils_spawner_Spawner
* Method: configureNativeTrace
* Signature: (ZZZZ)V
*/
JNIEXPORT void JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_configureNativeTrace(JNIEnv *, jclass, jboolean,
jboolean, jboolean, jboolean);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -24,18 +24,7 @@
#include "exec0.h" #include "exec0.h"
#include <org_eclipse_cdt_utils_spawner_Spawner.h> #include <org_eclipse_cdt_utils_spawner_Spawner.h>
static bool isTraceEnabled(void) { static bool trace_enabled = false;
static bool initialized = false;
static bool enabled = false;
if (!initialized) {
enabled = getenv("TRACE_ORG_ECLIPSE_CDT_SPAWNER") != NULL;
initialized = true;
}
return enabled;
}
static void print_array(FILE *stream, const char *str, char **c_array) { static void print_array(FILE *stream, const char *str, char **c_array) {
if (c_array) { if (c_array) {
@ -116,7 +105,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec2(JNIEnv *
goto bail_out; goto bail_out;
} }
if (isTraceEnabled()) { if (trace_enabled) {
print_array(stderr, "command:", cmd); print_array(stderr, "command:", cmd);
print_array(stderr, "Envp:", envp); print_array(stderr, "Envp:", envp);
fprintf(stderr, "dirpath: %s\n", dirpath); fprintf(stderr, "dirpath: %s\n", dirpath);
@ -160,7 +149,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1(JNIEnv *
goto bail_out; goto bail_out;
} }
if (isTraceEnabled()) { if (trace_enabled) {
print_array(stderr, "command:", cmd); print_array(stderr, "command:", cmd);
print_array(stderr, "Envp:", envp); print_array(stderr, "Envp:", envp);
fprintf(stderr, "dirpath: %s\n", dirpath); fprintf(stderr, "dirpath: %s\n", dirpath);
@ -213,7 +202,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0(JNIEnv *
goto bail_out; goto bail_out;
} }
if (isTraceEnabled()) { if (trace_enabled) {
print_array(stderr, "command:", cmd); print_array(stderr, "command:", cmd);
print_array(stderr, "Envp:", envp); print_array(stderr, "Envp:", envp);
fprintf(stderr, "dirpath: %s\n", dirpath); fprintf(stderr, "dirpath: %s\n", dirpath);
@ -235,11 +224,6 @@ bail_out:
return pid; return pid;
} }
/*
* Class: org_eclipse_cdt_utils_spawner_Spawner
* Method: raise
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise(JNIEnv *env, jobject jobj, jint pid, jint sig) { JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise(JNIEnv *env, jobject jobj, jint pid, jint sig) {
int status = -1; int status = -1;
@ -283,11 +267,13 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise(JNIEnv *
return status; return status;
} }
/*
* Class: org_eclipse_cdt_utils_spawner_Spawner
* Method: waitFor
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor(JNIEnv *env, jobject jobj, jint pid) { JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor(JNIEnv *env, jobject jobj, jint pid) {
return wait0(pid); return wait0(pid);
} }
JNIEXPORT void JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_configureNativeTrace(
JNIEnv *env, jclass cls, jboolean spawner, jboolean spawnerDetails, jboolean starter, jboolean readReport) {
if (spawner) {
trace_enabled = true;
}
}

View file

@ -26,7 +26,7 @@
#include "util.h" #include "util.h"
#include "org_eclipse_cdt_utils_spawner_Spawner.h" #include <org_eclipse_cdt_utils_spawner_Spawner.h>
#define PIPE_SIZE 512 // Size of pipe buffer #define PIPE_SIZE 512 // Size of pipe buffer
#define MAX_CMD_SIZE 2049 // Initial size of command line #define MAX_CMD_SIZE 2049 // Initial size of command line
@ -133,7 +133,7 @@ static bool createStandardNamedPipe(HANDLE *handle, DWORD stdHandle, int pid, in
dwOpenMode = PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED; dwOpenMode = PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED;
break; break;
default: default:
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Invalid STD handle given %i", stdHandle); cdtTrace(L"Invalid STD handle given %i", stdHandle);
} }
return false; return false;
@ -142,7 +142,7 @@ static bool createStandardNamedPipe(HANDLE *handle, DWORD stdHandle, int pid, in
HANDLE pipe = CreateNamedPipeW(pipeName, dwOpenMode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, HANDLE pipe = CreateNamedPipeW(pipeName, dwOpenMode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL); PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL);
if (INVALID_HANDLE_VALUE == pipe) { if (INVALID_HANDLE_VALUE == pipe) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Failed to create named pipe: %s\n", pipeName); cdtTrace(L"Failed to create named pipe: %s\n", pipeName);
} }
return false; return false;
@ -150,7 +150,7 @@ static bool createStandardNamedPipe(HANDLE *handle, DWORD stdHandle, int pid, in
SetHandleInformation(pipe, HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(pipe, HANDLE_FLAG_INHERIT, TRUE);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Successfully created pipe %s -> %p\n", pipeName, pipe); cdtTrace(L"Successfully created pipe %s -> %p\n", pipeName, pipe);
} }
@ -164,12 +164,12 @@ static bool createNamedEvent(EventInfo_t *eventInfo, BOOL manualReset, const wch
HANDLE event = CreateEventW(NULL, manualReset, FALSE, eventName); HANDLE event = CreateEventW(NULL, manualReset, FALSE, eventName);
if (!event) { if (!event) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Failed to create event %s -> %i\n", eventName, GetLastError()); cdtTrace(L"Failed to create event %s -> %i\n", eventName, GetLastError());
} }
return false; return false;
} else if (GetLastError() == ERROR_ALREADY_EXISTS) { } else if (GetLastError() == ERROR_ALREADY_EXISTS) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Event %s already exist -> %p\n", eventName, event); cdtTrace(L"Event %s already exist -> %p\n", eventName, event);
} }
return false; return false;
@ -179,13 +179,13 @@ static bool createNamedEvent(EventInfo_t *eventInfo, BOOL manualReset, const wch
eventInfo->name = wcsdup(eventName); eventInfo->name = wcsdup(eventName);
if (!eventInfo->name) { if (!eventInfo->name) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Failed to allocate memory for event %s -> %p\n", eventName, event); cdtTrace(L"Failed to allocate memory for event %s -> %p\n", eventName, event);
} }
return false; return false;
} }
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Successfully created event %s -> %p\n", eventName, event); cdtTrace(L"Successfully created event %s -> %p\n", eventName, event);
} }
@ -282,7 +282,7 @@ static bool createCommandLine(JNIEnv *env, jobjectArray cmdarray, wchar_t **cmdL
static bool createEnvironmentBlock(JNIEnv *env, jobjectArray envp, wchar_t **block) { static bool createEnvironmentBlock(JNIEnv *env, jobjectArray envp, wchar_t **block) {
int nEnvVars = (*env)->GetArrayLength(env, envp); int nEnvVars = (*env)->GetArrayLength(env, envp);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"There are %i environment variables \n", nEnvVars); cdtTrace(L"There are %i environment variables \n", nEnvVars);
} }
@ -292,36 +292,39 @@ static bool createEnvironmentBlock(JNIEnv *env, jobjectArray envp, wchar_t **blo
} }
int nPos = 0; int nPos = 0;
int nBlkSize = MAX_ENV_SIZE; int bufferSize = MAX_ENV_SIZE;
wchar_t *buffer = (wchar_t *)malloc(nBlkSize * sizeof(wchar_t)); wchar_t *buffer = (wchar_t *)malloc(bufferSize * sizeof(wchar_t));
for (int i = 0; i < nEnvVars; ++i) { for (int i = 0; i < nEnvVars; ++i) {
jstring item = (jstring)(*env)->GetObjectArrayElement(env, envp, i); jstring item = (jstring)(*env)->GetObjectArrayElement(env, envp, i);
jsize len = (*env)->GetStringLength(env, item);
const jchar *str = (*env)->GetStringChars(env, item, 0); const jchar *str = (*env)->GetStringChars(env, item, 0);
if (str) { if (str) {
while (nBlkSize - nPos <= len + 2) { // +2 for two '\0' int len = wcslen(str);
nBlkSize += MAX_ENV_SIZE; while (bufferSize - nPos <= len + 2) { // +2 for two '\0'
wchar_t *tmp = (wchar_t *)realloc(buffer, nBlkSize * sizeof(wchar_t)); bufferSize += MAX_ENV_SIZE;
wchar_t *tmp = (wchar_t *)realloc(buffer, bufferSize * sizeof(wchar_t));
if (tmp) { if (tmp) {
buffer = tmp; buffer = tmp;
} else { } else {
free(buffer); free(buffer);
(*env)->ReleaseStringChars(env, item, str);
ThrowByName(env, "java/io/IOException", "Not enough memory"); ThrowByName(env, "java/io/IOException", "Not enough memory");
return false; return false;
} }
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Realloc environment block; new length is %i \n", nBlkSize); cdtTrace(L"Realloc environment block; new length is %i \n", bufferSize);
} }
} }
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"%s\n", (const wchar_t *)str); cdtTrace(L"%s\n", (const wchar_t *)str);
} }
wcsncpy(buffer + nPos, (const wchar_t *)str, len); wcsncpy(buffer + nPos, str, len);
nPos += len; nPos += len;
buffer[nPos++] = _T('\0'); buffer[nPos++] = _T('\0');
(*env)->ReleaseStringChars(env, item, str); (*env)->ReleaseStringChars(env, item, str);
} }
} }
buffer[nPos] = _T('\0'); buffer[nPos] = _T('\0');
*block = buffer; *block = buffer;
@ -398,14 +401,15 @@ extern "C"
// Prepare command line // Prepare command line
wchar_t *cmdLine = NULL; wchar_t *cmdLine = NULL;
if (!createCommandLine(env, cmdarray, &cmdLine, L"\"%sstarter.exe\" %i %i %s %s %s %s %s ", path, // if (!createCommandLine(env, cmdarray, &cmdLine, L"\"%sstarter.exe\" %i %i %s %s %s %s %s %i ", path, //
pid, // pid, //
nLocalCounter, // nLocalCounter, //
pCurProcInfo->eventBreak.name, // pCurProcInfo->eventBreak.name, //
pCurProcInfo->eventWait.name, // pCurProcInfo->eventWait.name, //
pCurProcInfo->eventTerminate.name, // pCurProcInfo->eventTerminate.name, //
pCurProcInfo->eventKill.name, // pCurProcInfo->eventKill.name, //
pCurProcInfo->eventCtrlc.name)) { pCurProcInfo->eventCtrlc.name, //
isTraceEnabled(CDT_TRACE_SPAWNER_STARTER))) {
// Exception already thrown, just clean up // Exception already thrown, just clean up
cleanUpProcBlock(pCurProcInfo); cleanUpProcBlock(pCurProcInfo);
CLOSE_HANDLES(stdHandles); CLOSE_HANDLES(stdHandles);
@ -441,7 +445,7 @@ extern "C"
flags |= CREATE_NO_WINDOW; flags |= CREATE_NO_WINDOW;
flags |= CREATE_UNICODE_ENVIRONMENT; flags |= CREATE_UNICODE_ENVIRONMENT;
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(cmdLine); cdtTrace(cmdLine);
} }
@ -474,13 +478,13 @@ extern "C"
int what = WaitForMultipleObjects(2, h, FALSE, INFINITE); int what = WaitForMultipleObjects(2, h, FALSE, INFINITE);
if (what != WAIT_OBJECT_0) { // CreateProcess failed if (what != WAIT_OBJECT_0) { // CreateProcess failed
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Process %i failed\n", pi.dwProcessId); cdtTrace(L"Process %i failed\n", pi.dwProcessId);
} }
cleanUpProcBlock(pCurProcInfo); cleanUpProcBlock(pCurProcInfo);
CLOSE_HANDLES(stdHandles); CLOSE_HANDLES(stdHandles);
ThrowByName(env, "java/io/IOException", "Launching failed"); ThrowByName(env, "java/io/IOException", "Launching failed");
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Process failed\n"); cdtTrace(L"Process failed\n");
} }
} else { } else {
@ -498,7 +502,7 @@ extern "C"
memcpy(piCopy, &pi, sizeof(PROCESS_INFORMATION)); memcpy(piCopy, &pi, sizeof(PROCESS_INFORMATION));
_beginthread(waitProcTermination, 0, (void *)piCopy); _beginthread(waitProcTermination, 0, (void *)piCopy);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Process started\n"); cdtTrace(L"Process started\n");
} }
} }
@ -624,7 +628,7 @@ extern "C"
return -1; return -1;
} }
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Spawner received signal %i for process %i\n", signal, pCurProcInfo->pid); cdtTrace(L"Spawner received signal %i for process %i\n", signal, pCurProcInfo->pid);
} }
@ -644,22 +648,22 @@ extern "C"
ret = 0; ret = 0;
break; break;
case SIG_TERM: case SIG_TERM:
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Spawner received TERM signal for process %i\n", pCurProcInfo->pid); cdtTrace(L"Spawner received TERM signal for process %i\n", pCurProcInfo->pid);
} }
SetEvent(pCurProcInfo->eventTerminate.handle); SetEvent(pCurProcInfo->eventTerminate.handle);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Spawner signaled TERM event\n"); cdtTrace(L"Spawner signaled TERM event\n");
} }
ret = 0; ret = 0;
break; break;
case SIG_KILL: case SIG_KILL:
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Spawner received KILL signal for process %i\n", pCurProcInfo->pid); cdtTrace(L"Spawner received KILL signal for process %i\n", pCurProcInfo->pid);
} }
SetEvent(pCurProcInfo->eventKill.handle); SetEvent(pCurProcInfo->eventKill.handle);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Spawner signaled KILL event\n"); cdtTrace(L"Spawner signaled KILL event\n");
} }
ret = 0; ret = 0;
@ -825,7 +829,7 @@ void _cdecl waitProcTermination(void *pv) {
for (int i = 0; i < MAX_PROCS; i++) { for (int i = 0; i < MAX_PROCS; i++) {
if (pInfo[i].pid == pi->dwProcessId) { if (pInfo[i].pid == pi->dwProcessId) {
cleanUpProcBlock(pInfo + i); cleanUpProcBlock(pInfo + i);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"waitProcTermination: set PID %i to 0\n", pi->dwProcessId); cdtTrace(L"waitProcTermination: set PID %i to 0\n", pi->dwProcessId);
} }
} }
@ -834,3 +838,28 @@ void _cdecl waitProcTermination(void *pv) {
free(pi); free(pi);
} }
#ifdef __cplusplus
extern "C"
#endif
JNIEXPORT void JNICALL
Java_org_eclipse_cdt_utils_spawner_Spawner_configureNativeTrace(JNIEnv *env, jclass cls, jboolean spawner,
jboolean spawnerDetails, jboolean starter,
jboolean readReport) {
if (spawner) {
enableTraceFor(CDT_TRACE_SPAWNER);
}
if (spawnerDetails) {
enableTraceFor(CDT_TRACE_SPAWNER_DETAILS);
}
if (starter) {
enableTraceFor(CDT_TRACE_SPAWNER_STARTER);
}
if (readReport) {
enableTraceFor(CDT_TRACE_SPAWNER_READ_REPORT);
}
}

View file

@ -23,7 +23,7 @@
#include "util.h" #include "util.h"
#include "org_eclipse_cdt_utils_spawner_Spawner.h" #include <org_eclipse_cdt_utils_spawner_Spawner.h>
void ThrowByName(JNIEnv *env, const char *name, const char *msg); void ThrowByName(JNIEnv *env, const char *name, const char *msg);
@ -80,7 +80,7 @@ extern "C"
LocalFree(lpMsgBuf); LocalFree(lpMsgBuf);
} }
if (isTraceEnabled(CDT_TRACE_MONITOR) && isTraceEnabled(CDT_TRACE_READ_REPORT)) { if (isTraceEnabled(CDT_TRACE_SPAWNER) && isTraceEnabled(CDT_TRACE_SPAWNER_READ_REPORT)) {
cdtTrace(L"Start read %p\n", handle); cdtTrace(L"Start read %p\n", handle);
} }
@ -104,7 +104,7 @@ extern "C"
} }
if (err != 0) { if (err != 0) {
char *lpMsgBuf; char *lpMsgBuf;
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Read failed - %p, error %i\n", handle, err); cdtTrace(L"Read failed - %p, error %i\n", handle, err);
} }
if (err != if (err !=
@ -121,7 +121,7 @@ extern "C"
} else { } else {
// buffer overflow? // buffer overflow?
// according to msdn this happens in message read mode only // according to msdn this happens in message read mode only
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Buffer full - %p, bytes read: %i\n", handle, nNumberOfBytesRead); cdtTrace(L"Buffer full - %p, bytes read: %i\n", handle, nNumberOfBytesRead);
} }
// nNumberOfBytesRead can be 0 here for unknown reason (bug 269223) // nNumberOfBytesRead can be 0 here for unknown reason (bug 269223)
@ -147,7 +147,7 @@ extern "C"
} }
} }
CloseHandle(overlapped.hEvent); CloseHandle(overlapped.hEvent);
if (isTraceEnabled(CDT_TRACE_MONITOR) && isTraceEnabled(CDT_TRACE_READ_REPORT)) { if (isTraceEnabled(CDT_TRACE_SPAWNER) && isTraceEnabled(CDT_TRACE_SPAWNER_READ_REPORT)) {
cdtTrace(L"End read %p - bytes read: %d\n", handle, nBuffOffset); cdtTrace(L"End read %p - bytes read: %d\n", handle, nBuffOffset);
} }
return nBuffOffset; // This is a real full readed length return nBuffOffset; // This is a real full readed length
@ -160,11 +160,11 @@ extern "C"
Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_close0(JNIEnv *env, jobject proc, jobject channel) { Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_close0(JNIEnv *env, jobject proc, jobject channel) {
int rc; int rc;
HANDLE handle = channelToHandle(env, channel); HANDLE handle = channelToHandle(env, channel);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Close %p\n", handle); cdtTrace(L"Close %p\n", handle);
} }
rc = (CloseHandle(handle) ? 0 : -1); rc = (CloseHandle(handle) ? 0 : -1);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Closed %p\n", handle); cdtTrace(L"Closed %p\n", handle);
} }
return (rc ? GetLastError() : 0); return (rc ? GetLastError() : 0);
@ -221,12 +221,12 @@ extern "C"
Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_close0(JNIEnv *env, jobject proc, jobject channel) { Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_close0(JNIEnv *env, jobject proc, jobject channel) {
int rc; int rc;
HANDLE handle = channelToHandle(env, channel); HANDLE handle = channelToHandle(env, channel);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Close %p\n", handle); cdtTrace(L"Close %p\n", handle);
} }
FlushFileBuffers(handle); FlushFileBuffers(handle);
rc = (CloseHandle(handle) ? 0 : -1); rc = (CloseHandle(handle) ? 0 : -1);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Closed %p\n", handle); cdtTrace(L"Closed %p\n", handle);
} }
return (rc ? GetLastError() : 0); return (rc ? GetLastError() : 0);

View file

@ -20,9 +20,7 @@
#include "util.h" #include "util.h"
#include "org_eclipse_cdt_utils_spawner_Spawner.h" #include <org_eclipse_cdt_utils_spawner_Spawner.h>
extern void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg);
static HWND consoleHWND; static HWND consoleHWND;
@ -97,7 +95,7 @@ int interruptProcess(int pid) {
int rc = 0; int rc = 0;
consoleHWND = NULL; consoleHWND = NULL;
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Try to interrupt process %i\n", pid); cdtTrace(L"Try to interrupt process %i\n", pid);
} }
// Find console // Find console
@ -155,11 +153,11 @@ int interruptProcess(int pid) {
if (child_thread) { if (child_thread) {
AttachThreadInput(GetCurrentThreadId(), child_thread, FALSE); AttachThreadInput(GetCurrentThreadId(), child_thread, FALSE);
} }
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Sent Ctrl-C & Ctrl-Break to process %i\n", pid); cdtTrace(L"Sent Ctrl-C & Ctrl-Break to process %i\n", pid);
} }
} }
} else if (isTraceEnabled(CDT_TRACE_MONITOR)) { } else if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Cannot find console for process %i\n", pid); cdtTrace(L"Cannot find console for process %i\n", pid);
} }

View file

@ -143,7 +143,7 @@ static bool openNamedPipeAsStdHandle(HANDLE *handle, DWORD stdHandle, int parent
dwShareMode = FILE_SHARE_WRITE; dwShareMode = FILE_SHARE_WRITE;
break; break;
default: default:
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Invalid STD handle given %i", stdHandle); cdtTrace(L"Invalid STD handle given %i", stdHandle);
} }
return false; return false;
@ -151,7 +151,7 @@ static bool openNamedPipeAsStdHandle(HANDLE *handle, DWORD stdHandle, int parent
*handle = CreateFileW(pipeName, dwDesiredAccess, dwShareMode, NULL, OPEN_EXISTING, 0, sa); *handle = CreateFileW(pipeName, dwDesiredAccess, dwShareMode, NULL, OPEN_EXISTING, 0, sa);
if (INVALID_HANDLE_VALUE == *handle) { if (INVALID_HANDLE_VALUE == *handle) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Failed to open pipe: %s -> %p\n", pipeName, handle); cdtTrace(L"Failed to open pipe: %s -> %p\n", pipeName, handle);
} }
return false; return false;
@ -160,13 +160,13 @@ static bool openNamedPipeAsStdHandle(HANDLE *handle, DWORD stdHandle, int parent
SetHandleInformation(*handle, HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(*handle, HANDLE_FLAG_INHERIT, TRUE);
if (!SetStdHandle(stdHandle, *handle)) { if (!SetStdHandle(stdHandle, *handle)) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Failed to reassign standard stream to pipe %s: %i\n", pipeName, GetLastError()); cdtTrace(L"Failed to reassign standard stream to pipe %s: %i\n", pipeName, GetLastError());
} }
return false; return false;
} }
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Successfully assigned pipe %s -> %p\n", pipeName, *handle); cdtTrace(L"Successfully assigned pipe %s -> %p\n", pipeName, *handle);
} }
@ -191,7 +191,7 @@ bool createCommandLine(int argc, wchar_t **argv, wchar_t **cmdLine) {
int required = nPos + len + 2; // 2 => space + \0 int required = nPos + len + 2; // 2 => space + \0
if (required > 32 * 1024) { if (required > 32 * 1024) {
free(buffer); free(buffer);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Command line too long!\n"); cdtTrace(L"Command line too long!\n");
} }
return false; return false;
@ -212,7 +212,7 @@ bool createCommandLine(int argc, wchar_t **argv, wchar_t **cmdLine) {
} else { } else {
// Failed to realloc memory // Failed to realloc memory
free(buffer); free(buffer);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Not enough memory to build cmd line!\n"); cdtTrace(L"Not enough memory to build cmd line!\n");
} }
return false; return false;
@ -235,7 +235,7 @@ bool createCommandLine(int argc, wchar_t **argv, wchar_t **cmdLine) {
buffer[nPos] = _T('\0'); buffer[nPos] = _T('\0');
} else { } else {
free(buffer); free(buffer);
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Invalid argument!\n"); cdtTrace(L"Invalid argument!\n");
} }
return false; return false;
@ -252,11 +252,20 @@ 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 < 8) { if (argc < 9) {
wprintf(L"Usage: %s (parent pid) (counter) (four inheritable event handles) (CommandLineToSpawn)\n", argv[0]); wprintf(
L"Usage: %s (parent pid) (counter) (four inheritable event handles) (trace enable) (CommandLineToSpawn)\n",
argv[0]);
return 0; return 0;
} }
// Activate tracing...
if (wcstol(argv[8], NULL, 2)) {
for (int i = 0; i < sizeof(ALL_TRACE_KINDS) / sizeof(ALL_TRACE_KINDS[0]); i++) {
enableTraceFor(ALL_TRACE_KINDS[i]);
}
}
STARTUPINFOW si = {sizeof(si)}; STARTUPINFOW si = {sizeof(si)};
PROCESS_INFORMATION pi = {0}; PROCESS_INFORMATION pi = {0};
DWORD dwExitCode = 0; DWORD dwExitCode = 0;
@ -293,7 +302,7 @@ int main() {
return -1; return -1;
} }
if (isTraceEnabled(CDT_TRACE_MONITOR_DETAILS)) { if (isTraceEnabled(CDT_TRACE_SPAWNER_DETAILS)) {
wchar_t *lpvEnv = GetEnvironmentStringsW(); wchar_t *lpvEnv = GetEnvironmentStringsW();
if (lpvEnv) { if (lpvEnv) {
@ -322,23 +331,23 @@ int main() {
ZeroMemory(&jobInfo, sizeof(jobInfo)); ZeroMemory(&jobInfo, sizeof(jobInfo));
jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK; jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK;
if (!SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jobInfo, sizeof(jobInfo))) { if (!SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jobInfo, sizeof(jobInfo))) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Cannot set job information\n"); cdtTrace(L"Cannot set job information\n");
DisplayErrorMessage(); DisplayErrorMessage();
} }
} }
} else if (isTraceEnabled(CDT_TRACE_MONITOR)) { } else if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Cannot create job object\n"); cdtTrace(L"Cannot create job object\n");
DisplayErrorMessage(); DisplayErrorMessage();
} }
// Construct the full command line // Construct the full command line
wchar_t *cmdLine = NULL; wchar_t *cmdLine = NULL;
if (!createCommandLine(argc - 8, &argv[8], &cmdLine)) { if (!createCommandLine(argc - 9, &argv[9], &cmdLine)) {
return 0; return 0;
} }
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Starting: %s\n", cmdLine); cdtTrace(L"Starting: %s\n", cmdLine);
} }
@ -359,7 +368,7 @@ int main() {
free(cmdLine); free(cmdLine);
cmdLine = NULL; cmdLine = NULL;
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Process %i started\n", pi.dwProcessId); cdtTrace(L"Process %i started\n", pi.dwProcessId);
} }
SetEvent(waitEvent); // Means that process has been spawned SetEvent(waitEvent); // Means that process has been spawned
@ -368,7 +377,7 @@ int main() {
if (hJob) { if (hJob) {
if (!AssignProcessToJobObject(hJob, pi.hProcess)) { if (!AssignProcessToJobObject(hJob, pi.hProcess)) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Cannot assign process %i to a job\n", pi.dwProcessId); cdtTrace(L"Cannot assign process %i to a job\n", pi.dwProcessId);
DisplayErrorMessage(); DisplayErrorMessage();
} }
@ -382,7 +391,7 @@ int main() {
switch (event) { switch (event) {
case WAIT_OBJECT_0 + 0: // SIGINT case WAIT_OBJECT_0 + 0: // SIGINT
case WAIT_OBJECT_0 + 4: // CTRL-C case WAIT_OBJECT_0 + 4: // CTRL-C
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"starter (PID %i) received CTRL-C event\n", GetCurrentProcessId()); cdtTrace(L"starter (PID %i) received CTRL-C event\n", GetCurrentProcessId());
} }
if ((event == (WAIT_OBJECT_0 + 0)) && isCygwin(h[1])) { if ((event == (WAIT_OBJECT_0 + 0)) && isCygwin(h[1])) {
@ -402,7 +411,7 @@ int main() {
case WAIT_OBJECT_0 + 1: // App terminated normally case WAIT_OBJECT_0 + 1: // App terminated normally
// Make it's exit code our exit code // Make it's exit code our exit code
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"starter: launched process has been terminated(PID %i)\n", pi.dwProcessId); cdtTrace(L"starter: launched process has been terminated(PID %i)\n", pi.dwProcessId);
} }
GetExitCodeProcess(pi.hProcess, &dwExitCode); GetExitCodeProcess(pi.hProcess, &dwExitCode);
@ -417,7 +426,7 @@ int main() {
case WAIT_OBJECT_0 + 3: // KILL case WAIT_OBJECT_0 + 3: // KILL
{ {
const wchar_t *signal = (event == WAIT_OBJECT_0 + 2) ? L"TERM" : L"KILL"; const wchar_t *signal = (event == WAIT_OBJECT_0 + 2) ? L"TERM" : L"KILL";
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"starter received %s event (PID %i)\n", signal, GetCurrentProcessId()); cdtTrace(L"starter received %s event (PID %i)\n", signal, GetCurrentProcessId());
} }
if (isCygwin(h[1])) { if (isCygwin(h[1])) {
@ -436,7 +445,7 @@ int main() {
if (hJob) { if (hJob) {
if (!TerminateJobObject(hJob, (DWORD)-1)) { if (!TerminateJobObject(hJob, (DWORD)-1)) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Cannot terminate job\n"); cdtTrace(L"Cannot terminate job\n");
DisplayErrorMessage(); DisplayErrorMessage();
} }
@ -449,14 +458,14 @@ int main() {
default: default:
// Unexpected code // Unexpected code
if (isTraceEnabled(CDT_TRACE_MONITOR)) { if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
DisplayErrorMessage(); DisplayErrorMessage();
} }
exitProc = TRUE; exitProc = TRUE;
break; break;
} }
} }
} else if (isTraceEnabled(CDT_TRACE_MONITOR)) { } else if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Cannot start: %s\n", cmdLine); cdtTrace(L"Cannot start: %s\n", cmdLine);
free(cmdLine); free(cmdLine);
@ -478,5 +487,4 @@ void DisplayErrorMessage() {
// Free the buffer. // Free the buffer.
LocalFree(lpMsgBuf); LocalFree(lpMsgBuf);
} }
//////////////////////////////// End of File ////////////////////////////////// //////////////////////////////// End of File //////////////////////////////////

View file

@ -17,29 +17,43 @@
#include <stdio.h> #include <stdio.h>
#include <tchar.h> #include <tchar.h>
bool isTraceEnabled(const TraceKind_t traceKind) { static bool spawner = false;
static bool initialized = false; static bool spawnerDetails = false;
static bool monitor = false; static bool spawnerStarter = false;
static bool monitorDetails = false;
static bool readReport = false; static bool readReport = false;
if (!initialized) { void enableTraceFor(const TraceKind_t traceKind) {
monitor = _wgetenv(L"TRACE_ORG_ECLIPSE_CDT_MONITOR") != NULL; switch (traceKind) {
monitorDetails = _wgetenv(L"TRACE_ORG_ECLIPSE_CDT_MONITORDETAILS") != NULL; case CDT_TRACE_SPAWNER:
readReport = _wgetenv(L"TRACE_ORG_ECLIPSE_CDT_READREPORT") != NULL; spawner = true;
break;
initialized = true; case CDT_TRACE_SPAWNER_DETAILS:
spawnerDetails = true;
break;
case CDT_TRACE_SPAWNER_STARTER:
spawnerStarter = true;
break;
case CDT_TRACE_SPAWNER_READ_REPORT:
readReport = true;
break;
default:
cdtTrace(L"%S: Invalid trace kind supplied: %d\n", __func__, traceKind);
break;
}
} }
bool isTraceEnabled(const TraceKind_t traceKind) {
switch (traceKind) { switch (traceKind) {
case CDT_TRACE_MONITOR: case CDT_TRACE_SPAWNER:
return monitor; return spawner;
case CDT_TRACE_MONITOR_DETAILS: case CDT_TRACE_SPAWNER_DETAILS:
return monitorDetails; return spawnerDetails;
case CDT_TRACE_READ_REPORT: case CDT_TRACE_SPAWNER_STARTER:
return spawnerStarter;
case CDT_TRACE_SPAWNER_READ_REPORT:
return readReport; return readReport;
default: default:
cdtTrace(L"Invalid trace kind supplied: %d\n", traceKind); cdtTrace(L"%S: Invalid trace kind supplied: %d\n", __func__, traceKind);
return false; return false;
} }
} }

View file

@ -18,8 +18,16 @@
#include <stdbool.h> #include <stdbool.h>
#include <windows.h> #include <windows.h>
typedef enum { CDT_TRACE_MONITOR, CDT_TRACE_MONITOR_DETAILS, CDT_TRACE_READ_REPORT } TraceKind_t; typedef enum {
CDT_TRACE_SPAWNER,
CDT_TRACE_SPAWNER_DETAILS,
CDT_TRACE_SPAWNER_STARTER,
CDT_TRACE_SPAWNER_READ_REPORT
} TraceKind_t;
static const TraceKind_t ALL_TRACE_KINDS[] = {CDT_TRACE_SPAWNER, CDT_TRACE_SPAWNER_DETAILS, CDT_TRACE_SPAWNER_STARTER,
CDT_TRACE_SPAWNER_READ_REPORT};
void enableTraceFor(const TraceKind_t traceKind);
bool isTraceEnabled(const TraceKind_t traceKind); bool isTraceEnabled(const TraceKind_t traceKind);
void cdtTrace(const wchar_t *fmt, ...); void cdtTrace(const wchar_t *fmt, ...);

View file

@ -457,6 +457,10 @@ public class Spawner extends Process {
static { static {
try { try {
System.loadLibrary("spawner"); //$NON-NLS-1$ System.loadLibrary("spawner"); //$NON-NLS-1$
configureNativeTrace(Platform.getDebugBoolean(CNativePlugin.PLUGIN_ID + "/debug/spawner"), //$NON-NLS-1$
Platform.getDebugBoolean(CNativePlugin.PLUGIN_ID + "/debug/spawner/details"), //$NON-NLS-1$
Platform.getDebugBoolean(CNativePlugin.PLUGIN_ID + "/debug/spawner/starter"), //$NON-NLS-1$
Platform.getDebugBoolean(CNativePlugin.PLUGIN_ID + "/debug/spawner/read_report")); //$NON-NLS-1$
} catch (SecurityException e) { } catch (SecurityException e) {
CNativePlugin.log(e); CNativePlugin.log(e);
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError e) {
@ -464,6 +468,12 @@ public class Spawner extends Process {
} }
} }
/**
* @since 6.0
*/
private static native void configureNativeTrace(boolean spawner, boolean spawnerDetails, boolean starter,
boolean readReport);
/** /**
* @since 6.0 * @since 6.0
*/ */