1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 17:56: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/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
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);
/*
* 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
}
#endif

View file

@ -24,18 +24,7 @@
#include "exec0.h"
#include <org_eclipse_cdt_utils_spawner_Spawner.h>
static bool isTraceEnabled(void) {
static bool initialized = false;
static bool enabled = false;
if (!initialized) {
enabled = getenv("TRACE_ORG_ECLIPSE_CDT_SPAWNER") != NULL;
initialized = true;
}
return enabled;
}
static bool trace_enabled = false;
static void print_array(FILE *stream, const char *str, char **c_array) {
if (c_array) {
@ -116,7 +105,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec2(JNIEnv *
goto bail_out;
}
if (isTraceEnabled()) {
if (trace_enabled) {
print_array(stderr, "command:", cmd);
print_array(stderr, "Envp:", envp);
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;
}
if (isTraceEnabled()) {
if (trace_enabled) {
print_array(stderr, "command:", cmd);
print_array(stderr, "Envp:", envp);
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;
}
if (isTraceEnabled()) {
if (trace_enabled) {
print_array(stderr, "command:", cmd);
print_array(stderr, "Envp:", envp);
fprintf(stderr, "dirpath: %s\n", dirpath);
@ -235,11 +224,6 @@ bail_out:
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) {
int status = -1;
@ -283,11 +267,13 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise(JNIEnv *
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) {
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 "org_eclipse_cdt_utils_spawner_Spawner.h"
#include <org_eclipse_cdt_utils_spawner_Spawner.h>
#define PIPE_SIZE 512 // Size of pipe buffer
#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;
break;
default:
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Invalid STD handle given %i", stdHandle);
}
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,
PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL);
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);
}
return false;
@ -150,7 +150,7 @@ static bool createStandardNamedPipe(HANDLE *handle, DWORD stdHandle, int pid, in
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);
}
@ -164,12 +164,12 @@ static bool createNamedEvent(EventInfo_t *eventInfo, BOOL manualReset, const wch
HANDLE event = CreateEventW(NULL, manualReset, FALSE, eventName);
if (!event) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Failed to create event %s -> %i\n", eventName, GetLastError());
}
return false;
} 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);
}
return false;
@ -179,13 +179,13 @@ static bool createNamedEvent(EventInfo_t *eventInfo, BOOL manualReset, const wch
eventInfo->name = wcsdup(eventName);
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);
}
return false;
}
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
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) {
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);
}
@ -292,36 +292,39 @@ static bool createEnvironmentBlock(JNIEnv *env, jobjectArray envp, wchar_t **blo
}
int nPos = 0;
int nBlkSize = MAX_ENV_SIZE;
wchar_t *buffer = (wchar_t *)malloc(nBlkSize * sizeof(wchar_t));
int bufferSize = MAX_ENV_SIZE;
wchar_t *buffer = (wchar_t *)malloc(bufferSize * sizeof(wchar_t));
for (int i = 0; i < nEnvVars; ++i) {
jstring item = (jstring)(*env)->GetObjectArrayElement(env, envp, i);
jsize len = (*env)->GetStringLength(env, item);
const jchar *str = (*env)->GetStringChars(env, item, 0);
if (str) {
while (nBlkSize - nPos <= len + 2) { // +2 for two '\0'
nBlkSize += MAX_ENV_SIZE;
wchar_t *tmp = (wchar_t *)realloc(buffer, nBlkSize * sizeof(wchar_t));
int len = wcslen(str);
while (bufferSize - nPos <= len + 2) { // +2 for two '\0'
bufferSize += MAX_ENV_SIZE;
wchar_t *tmp = (wchar_t *)realloc(buffer, bufferSize * sizeof(wchar_t));
if (tmp) {
buffer = tmp;
} else {
free(buffer);
(*env)->ReleaseStringChars(env, item, str);
ThrowByName(env, "java/io/IOException", "Not enough memory");
return false;
}
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Realloc environment block; new length is %i \n", nBlkSize);
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
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);
}
wcsncpy(buffer + nPos, (const wchar_t *)str, len);
wcsncpy(buffer + nPos, str, len);
nPos += len;
buffer[nPos++] = _T('\0');
(*env)->ReleaseStringChars(env, item, str);
}
}
buffer[nPos] = _T('\0');
*block = buffer;
@ -398,14 +401,15 @@ extern "C"
// Prepare command line
wchar_t *cmdLine = NULL;
if (!createCommandLine(env, cmdarray, &cmdLine, L"\"%sstarter.exe\" %i %i %s %s %s %s %s ", path, //
pid, //
nLocalCounter, //
pCurProcInfo->eventBreak.name, //
pCurProcInfo->eventWait.name, //
pCurProcInfo->eventTerminate.name, //
pCurProcInfo->eventKill.name, //
pCurProcInfo->eventCtrlc.name)) {
if (!createCommandLine(env, cmdarray, &cmdLine, L"\"%sstarter.exe\" %i %i %s %s %s %s %s %i ", path, //
pid, //
nLocalCounter, //
pCurProcInfo->eventBreak.name, //
pCurProcInfo->eventWait.name, //
pCurProcInfo->eventTerminate.name, //
pCurProcInfo->eventKill.name, //
pCurProcInfo->eventCtrlc.name, //
isTraceEnabled(CDT_TRACE_SPAWNER_STARTER))) {
// Exception already thrown, just clean up
cleanUpProcBlock(pCurProcInfo);
CLOSE_HANDLES(stdHandles);
@ -441,7 +445,7 @@ extern "C"
flags |= CREATE_NO_WINDOW;
flags |= CREATE_UNICODE_ENVIRONMENT;
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(cmdLine);
}
@ -474,13 +478,13 @@ extern "C"
int what = WaitForMultipleObjects(2, h, FALSE, INFINITE);
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);
}
cleanUpProcBlock(pCurProcInfo);
CLOSE_HANDLES(stdHandles);
ThrowByName(env, "java/io/IOException", "Launching failed");
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Process failed\n");
}
} else {
@ -498,7 +502,7 @@ extern "C"
memcpy(piCopy, &pi, sizeof(PROCESS_INFORMATION));
_beginthread(waitProcTermination, 0, (void *)piCopy);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Process started\n");
}
}
@ -624,7 +628,7 @@ extern "C"
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);
}
@ -644,22 +648,22 @@ extern "C"
ret = 0;
break;
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);
}
SetEvent(pCurProcInfo->eventTerminate.handle);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Spawner signaled TERM event\n");
}
ret = 0;
break;
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);
}
SetEvent(pCurProcInfo->eventKill.handle);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Spawner signaled KILL event\n");
}
ret = 0;
@ -825,7 +829,7 @@ void _cdecl waitProcTermination(void *pv) {
for (int i = 0; i < MAX_PROCS; i++) {
if (pInfo[i].pid == pi->dwProcessId) {
cleanUpProcBlock(pInfo + i);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"waitProcTermination: set PID %i to 0\n", pi->dwProcessId);
}
}
@ -834,3 +838,28 @@ void _cdecl waitProcTermination(void *pv) {
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 "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);
@ -80,7 +80,7 @@ extern "C"
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);
}
@ -104,7 +104,7 @@ extern "C"
}
if (err != 0) {
char *lpMsgBuf;
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Read failed - %p, error %i\n", handle, err);
}
if (err !=
@ -121,7 +121,7 @@ extern "C"
} else {
// buffer overflow?
// 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);
}
// nNumberOfBytesRead can be 0 here for unknown reason (bug 269223)
@ -147,7 +147,7 @@ extern "C"
}
}
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);
}
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) {
int rc;
HANDLE handle = channelToHandle(env, channel);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Close %p\n", handle);
}
rc = (CloseHandle(handle) ? 0 : -1);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Closed %p\n", handle);
}
return (rc ? GetLastError() : 0);
@ -221,12 +221,12 @@ extern "C"
Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_close0(JNIEnv *env, jobject proc, jobject channel) {
int rc;
HANDLE handle = channelToHandle(env, channel);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Close %p\n", handle);
}
FlushFileBuffers(handle);
rc = (CloseHandle(handle) ? 0 : -1);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Closed %p\n", handle);
}
return (rc ? GetLastError() : 0);

View file

@ -20,9 +20,7 @@
#include "util.h"
#include "org_eclipse_cdt_utils_spawner_Spawner.h"
extern void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg);
#include <org_eclipse_cdt_utils_spawner_Spawner.h>
static HWND consoleHWND;
@ -97,7 +95,7 @@ int interruptProcess(int pid) {
int rc = 0;
consoleHWND = NULL;
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Try to interrupt process %i\n", pid);
}
// Find console
@ -155,11 +153,11 @@ int interruptProcess(int pid) {
if (child_thread) {
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);
}
}
} else if (isTraceEnabled(CDT_TRACE_MONITOR)) {
} else if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
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;
break;
default:
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Invalid STD handle given %i", stdHandle);
}
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);
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);
}
return false;
@ -160,13 +160,13 @@ static bool openNamedPipeAsStdHandle(HANDLE *handle, DWORD stdHandle, int parent
SetHandleInformation(*handle, HANDLE_FLAG_INHERIT, TRUE);
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());
}
return false;
}
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
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
if (required > 32 * 1024) {
free(buffer);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Command line too long!\n");
}
return false;
@ -212,7 +212,7 @@ bool createCommandLine(int argc, wchar_t **argv, wchar_t **cmdLine) {
} else {
// Failed to realloc memory
free(buffer);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Not enough memory to build cmd line!\n");
}
return false;
@ -235,7 +235,7 @@ bool createCommandLine(int argc, wchar_t **argv, wchar_t **cmdLine) {
buffer[nPos] = _T('\0');
} else {
free(buffer);
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Invalid argument!\n");
}
return false;
@ -252,11 +252,20 @@ int main() {
wchar_t **argv = CommandLineToArgvW(GetCommandLine(), &argc);
// Make sure that we've been passed the right number of arguments
if (argc < 8) {
wprintf(L"Usage: %s (parent pid) (counter) (four inheritable event handles) (CommandLineToSpawn)\n", argv[0]);
if (argc < 9) {
wprintf(
L"Usage: %s (parent pid) (counter) (four inheritable event handles) (trace enable) (CommandLineToSpawn)\n",
argv[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)};
PROCESS_INFORMATION pi = {0};
DWORD dwExitCode = 0;
@ -293,7 +302,7 @@ int main() {
return -1;
}
if (isTraceEnabled(CDT_TRACE_MONITOR_DETAILS)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER_DETAILS)) {
wchar_t *lpvEnv = GetEnvironmentStringsW();
if (lpvEnv) {
@ -322,23 +331,23 @@ int main() {
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))) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Cannot set job information\n");
DisplayErrorMessage();
}
}
} else if (isTraceEnabled(CDT_TRACE_MONITOR)) {
} else if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Cannot create job object\n");
DisplayErrorMessage();
}
// Construct the full command line
wchar_t *cmdLine = NULL;
if (!createCommandLine(argc - 8, &argv[8], &cmdLine)) {
if (!createCommandLine(argc - 9, &argv[9], &cmdLine)) {
return 0;
}
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Starting: %s\n", cmdLine);
}
@ -359,7 +368,7 @@ int main() {
free(cmdLine);
cmdLine = NULL;
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Process %i started\n", pi.dwProcessId);
}
SetEvent(waitEvent); // Means that process has been spawned
@ -368,7 +377,7 @@ int main() {
if (hJob) {
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);
DisplayErrorMessage();
}
@ -382,7 +391,7 @@ int main() {
switch (event) {
case WAIT_OBJECT_0 + 0: // SIGINT
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());
}
if ((event == (WAIT_OBJECT_0 + 0)) && isCygwin(h[1])) {
@ -402,7 +411,7 @@ int main() {
case WAIT_OBJECT_0 + 1: // App terminated normally
// 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);
}
GetExitCodeProcess(pi.hProcess, &dwExitCode);
@ -417,7 +426,7 @@ int main() {
case WAIT_OBJECT_0 + 3: // 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());
}
if (isCygwin(h[1])) {
@ -436,7 +445,7 @@ int main() {
if (hJob) {
if (!TerminateJobObject(hJob, (DWORD)-1)) {
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Cannot terminate job\n");
DisplayErrorMessage();
}
@ -449,14 +458,14 @@ int main() {
default:
// Unexpected code
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
DisplayErrorMessage();
}
exitProc = TRUE;
break;
}
}
} else if (isTraceEnabled(CDT_TRACE_MONITOR)) {
} else if (isTraceEnabled(CDT_TRACE_SPAWNER)) {
cdtTrace(L"Cannot start: %s\n", cmdLine);
free(cmdLine);
@ -478,5 +487,4 @@ void DisplayErrorMessage() {
// Free the buffer.
LocalFree(lpMsgBuf);
}
//////////////////////////////// End of File //////////////////////////////////

View file

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

View file

@ -18,8 +18,16 @@
#include <stdbool.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);
void cdtTrace(const wchar_t *fmt, ...);

View file

@ -457,6 +457,10 @@ public class Spawner extends Process {
static {
try {
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) {
CNativePlugin.log(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
*/