1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-21 21:52:10 +02:00

Bug 568079: Do not require rebuild of natives to enable/disable tracing

Change-Id: I6e26c6febd56bcc23efe0ec65973b2f02a5fd809
Signed-off-by: Torbjörn Svensson <azoff@svenskalinuxforeningen.se>
This commit is contained in:
Torbjörn Svensson 2020-11-01 11:12:27 +01:00
parent b0d25c22eb
commit 2857a7a0b3
16 changed files with 302 additions and 254 deletions

View file

@ -72,7 +72,7 @@ rebuild: clean all
# However, x86_64-w64-mingw32-ld on Debian/Ubuntu has a patch that overrides the current date
# using the SOURCE_DATE_EPOCH environment variable. Call REPRODUCIBLE_BUILD_WRAPPER to make sure the
# same binary is produced for the same source each time.
$(OS_DIR_WIN32_X86_64)/starter.exe: win/starter.c
$(OS_DIR_WIN32_X86_64)/starter.exe: win/starter.c win/util.c
mkdir -p $(dir $@) && \
$(REPRODUCIBLE_BUILD_WRAPPER) \
x86_64-w64-mingw32-gcc $(COMMON_CFLAGS) -o $@ -Iinclude -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/win32" \
@ -80,7 +80,7 @@ $(OS_DIR_WIN32_X86_64)/starter.exe: win/starter.c
$^ \
-lpsapi
$(OS_DIR_WIN32_X86_64)/spawner.dll: win/iostream.c win/raise.c win/spawner.c win/Win32ProcessEx.c
$(OS_DIR_WIN32_X86_64)/spawner.dll: win/iostream.c win/raise.c win/spawner.c win/Win32ProcessEx.c win/util.c
mkdir -p $(dir $@) && \
$(REPRODUCIBLE_BUILD_WRAPPER) \
x86_64-w64-mingw32-gcc $(COMMON_CFLAGS) -o $@ -Iinclude -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/win32" \
@ -88,7 +88,7 @@ $(OS_DIR_WIN32_X86_64)/spawner.dll: win/iostream.c win/raise.c win/spawner.c win
$^ \
-Wl,--kill-at --shared
$(OS_DIR_WIN32_X86_64)/pty.dll: win/pty.cpp win/pty_dllmain.cpp
$(OS_DIR_WIN32_X86_64)/pty.dll: win/pty.cpp win/pty_dllmain.cpp win/util.c
mkdir -p $(dir $@) && \
$(REPRODUCIBLE_BUILD_WRAPPER) \
x86_64-w64-mingw32-g++ $(COMMON_CFLAGS) -o $@ -Iinclude -Iwin/include -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/win32" \

View file

@ -19,33 +19,51 @@
#include <signal.h>
#include <string.h>
#include <jni.h>
#include <stdbool.h>
#include "exec0.h"
#include <org_eclipse_cdt_utils_spawner_Spawner.h>
#define DEBUGIT 0
static bool isTraceEnabled(void) {
static bool initialized = false;
static bool enabled = false;
/*
* Header for class org_eclipse_cdt_utils_spawner_Spawner
*/
if (!initialized) {
enabled = getenv("TRACE_ORG_ECLIPSE_CDT_SPAWNER") != NULL;
#if DEBUGIT
static void print_array(char **c_array) {
initialized = true;
}
return enabled;
}
static void print_array(FILE *stream, const char *str, char **c_array) {
if (c_array) {
bool hasElement = false;
fprintf(stream, "%s [", str);
for (char **p = c_array; *p; p++) {
if (*p) {
fprintf(stderr, " %s", *p);
if (hasElement) {
fprintf(stream, ",");
}
hasElement = true;
fprintf(stream, "\n \"%s\"", *p);
}
}
if (hasElement) {
fprintf(stream, "\n");
}
fprintf(stream, "]\n");
} else {
fprintf(stderr, "null");
fprintf(stream, "%s null\n", str);
}
fprintf(stderr, "\n");
}
#endif
static char **alloc_c_array(JNIEnv *env, jobjectArray j_array) {
int i;
jint c_array_size = (*env)->GetArrayLength(env, j_array);
char **c_array = calloc(c_array_size + 1, sizeof(char *));
@ -53,7 +71,7 @@ static char **alloc_c_array(JNIEnv *env, jobjectArray j_array) {
return NULL;
}
for (i = 0; i < c_array_size; i++) {
for (int i = 0; i < c_array_size; i++) {
jstring j_str = (jstring)(*env)->GetObjectArrayElement(env, j_array, i);
const char *c_str = (*env)->GetStringUTFChars(env, j_str, NULL);
c_array[i] = (char *)strdup(c_str);
@ -98,14 +116,12 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec2(JNIEnv *
goto bail_out;
}
#if DEBUGIT
fprintf(stderr, "command:");
print_array(cmd);
fprintf(stderr, "Envp:");
print_array(envp);
fprintf(stderr, "dirpath: %s\n", dirpath);
fprintf(stderr, "pts_name: %s\n", pts_name);
#endif
if (isTraceEnabled()) {
print_array(stderr, "command:", cmd);
print_array(stderr, "Envp:", envp);
fprintf(stderr, "dirpath: %s\n", dirpath);
fprintf(stderr, "pts_name: %s\n", pts_name);
}
pid = exec_pty(cmd[0], cmd, envp, dirpath, fd, pts_name, masterFD, console);
if (pid < 0) {
@ -144,13 +160,11 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1(JNIEnv *
goto bail_out;
}
#if DEBUGIT
fprintf(stderr, "command:");
print_array(cmd);
fprintf(stderr, "Envp:");
print_array(envp);
fprintf(stderr, "dirpath: %s\n", dirpath);
#endif
if (isTraceEnabled()) {
print_array(stderr, "command:", cmd);
print_array(stderr, "Envp:", envp);
fprintf(stderr, "dirpath: %s\n", dirpath);
}
pid = exec0(cmd[0], cmd, envp, dirpath, NULL);
if (pid < 0) {
@ -199,13 +213,11 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0(JNIEnv *
goto bail_out;
}
#if DEBUGIT
fprintf(stderr, "command:");
print_array(cmd);
fprintf(stderr, "Envp:");
print_array(envp);
fprintf(stderr, "dirpath: %s\n", dirpath);
#endif
if (isTraceEnabled()) {
print_array(stderr, "command:", cmd);
print_array(stderr, "Envp:", envp);
fprintf(stderr, "dirpath: %s\n", dirpath);
}
pid = exec0(cmd[0], cmd, envp, dirpath, fd);
if (pid < 0) {
goto bail_out;

View file

@ -24,6 +24,8 @@
#include <windows.h>
#include <jni.h>
#include "util.h"
#include "org_eclipse_cdt_utils_spawner_Spawner.h"
#define PIPE_SIZE 512 // Size of pipe buffer
@ -159,9 +161,6 @@ extern "C"
wchar_t eventTerminateName[MAX_EVENT_NAME_LENGTH];
wchar_t eventKillName[MAX_EVENT_NAME_LENGTH];
wchar_t eventCtrlcName[MAX_EVENT_NAME_LENGTH];
#ifdef DEBUG_MONITOR
wchar_t buffer[4000];
#endif
int nLocalCounter;
wchar_t inPipeName[PIPE_NAME_LENGTH];
wchar_t outPipeName[PIPE_NAME_LENGTH];
@ -228,11 +227,9 @@ extern "C"
return 0;
}
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Opened pipes: %s, %s, %s\n"), inPipeName, outPipeName,
errPipeName);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Opened pipes: %s, %s, %s\n", inPipeName, outPipeName, errPipeName);
}
nCmdTokens = (*env)->GetArrayLength(env, cmdarray);
nEnvVars = (*env)->GetArrayLength(env, envp);
@ -298,10 +295,10 @@ extern "C"
}
szCmdLine[nPos] = _T('\0');
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("There are %i environment variables \n"), nEnvVars);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"There are %i environment variables \n", nEnvVars);
}
// Prepare environment block
if (nEnvVars > 0) {
nPos = 0;
@ -318,16 +315,13 @@ extern "C"
ThrowByName(env, "java/io/IOException", "Not enough memory");
return 0;
}
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]),
_T("Realloc environment block; new length is %i \n"), nBlkSize);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Realloc environment block; new length is %i \n", nBlkSize);
}
}
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"%s\n", str);
}
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("%s\n"), str);
OutputDebugStringW(buffer);
#endif
wcsncpy(szEnvBlock + nPos, str, len);
nPos += len;
szEnvBlock[nPos] = _T('\0');
@ -359,9 +353,9 @@ extern "C"
flags |= CREATE_NO_WINDOW;
flags |= CREATE_UNICODE_ENVIRONMENT;
#ifdef DEBUG_MONITOR
OutputDebugStringW(szCmdLine);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(szCmdLine);
}
// launches starter; we need it to create another console group to correctly process
// emulation of SYSint signal (Ctrl-C)
ret = CreateProcessW(0, /* executable name */
@ -404,15 +398,14 @@ extern "C"
what = WaitForMultipleObjects(2, h, FALSE, INFINITE);
if (what != WAIT_OBJECT_0) { // CreateProcess failed
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Process %i failed\n"), pi.dwProcessId);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Process %i failed\n", pi.dwProcessId);
}
cleanUpProcBlock(pCurProcInfo);
ThrowByName(env, "java/io/IOException", "Launching failed");
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Process failed\n"));
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Process failed\n");
}
} else {
ret = (long)(pCurProcInfo->uid);
@ -428,9 +421,9 @@ extern "C"
memcpy(piCopy, &pi, sizeof(PROCESS_INFORMATION));
_beginthread(waitProcTermination, 0, (void *)piCopy);
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Process started\n"));
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Process started\n");
}
}
LeaveCriticalSection(&cs);
}
@ -605,9 +598,6 @@ extern "C"
HANDLE hProc;
pProcInfo_t pCurProcInfo = findProcInfo(uid);
#ifdef DEBUG_MONITOR
wchar_t buffer[100];
#endif
if (NULL == pCurProcInfo) {
if (SIG_INT == signal) { // Try another way
@ -616,11 +606,9 @@ extern "C"
return -1;
}
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Spawner received signal %i for process %i\n"), signal,
pCurProcInfo->pid);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Spawner received signal %i for process %i\n", signal, pCurProcInfo->pid);
}
hProc = OpenProcess(SYNCHRONIZE, 0, pCurProcInfo->pid);
@ -638,28 +626,24 @@ extern "C"
ret = 0;
break;
case SIG_TERM:
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Spawner received TERM signal for process %i\n"),
pCurProcInfo->pid);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Spawner received TERM signal for process %i\n", pCurProcInfo->pid);
}
SetEvent(pCurProcInfo->eventTerminate);
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Spawner signaled TERM event\n"));
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Spawner signaled TERM event\n");
}
ret = 0;
break;
case SIG_KILL:
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Spawner received KILL signal for process %i\n"),
pCurProcInfo->pid);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Spawner received KILL signal for process %i\n", pCurProcInfo->pid);
}
SetEvent(pCurProcInfo->eventKill);
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Spawner signaled KILL event\n"));
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Spawner signaled KILL event\n");
}
ret = 0;
break;
case SIG_INT:
@ -830,9 +814,6 @@ void cleanUpProcBlock(pProcInfo_t pCurProcInfo) {
void _cdecl waitProcTermination(void *pv) {
PROCESS_INFORMATION *pi = (PROCESS_INFORMATION *)pv;
int i;
#ifdef DEBUG_MONITOR
wchar_t buffer[1000];
#endif
// wait for process termination
WaitForSingleObject(pi->hProcess, INFINITE);
@ -840,11 +821,9 @@ void _cdecl waitProcTermination(void *pv) {
for (i = 0; i < MAX_PROCS; ++i) {
if (pInfo[i].pid == pi->dwProcessId) {
cleanUpProcBlock(pInfo + i);
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("waitProcTermination: set PID %i to 0\n"),
pi->dwProcessId);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"waitProcTermination: set PID %i to 0\n", pi->dwProcessId);
}
}
}
CloseHandle(pi->hProcess);

View file

@ -21,9 +21,9 @@
#include <jni.h>
#include <windows.h>
#include "org_eclipse_cdt_utils_spawner_Spawner.h"
#include "util.h"
//#define READ_REPORT
#include "org_eclipse_cdt_utils_spawner_Spawner.h"
void ThrowByName(JNIEnv *env, const char *name, const char *msg);
@ -61,9 +61,6 @@ extern "C"
jbyte tmpBuf[BUFF_SIZE];
int nBuffOffset = 0;
HANDLE handle = channelToHandle(env, channel);
#ifdef DEBUG_MONITOR
_TCHAR buffer[1000];
#endif
OVERLAPPED overlapped;
overlapped.Offset = 0;
overlapped.OffsetHigh = 0;
@ -83,12 +80,9 @@ extern "C"
LocalFree(lpMsgBuf);
}
#ifdef DEBUG_MONITOR
#ifdef READ_REPORT
_stprintf(buffer, _T("Start read %i\n"), fd);
OutputDebugStringW(buffer);
#endif
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR) && isTraceEnabled(CDT_TRACE_READ_REPORT)) {
cdtTrace(L"Start read %p\n", handle);
}
while (len > nBuffOffset) {
DWORD nNumberOfBytesToRead = min(len - nBuffOffset, BUFF_SIZE);
@ -110,10 +104,9 @@ extern "C"
}
if (err != 0) {
char *lpMsgBuf;
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Read failed - %i, error %i\n"), fd, err);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Read failed - %p, error %i\n", handle, err);
}
if (err !=
ERROR_MORE_DATA) { // Otherwise error means just that there are more data than buffer can accept
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
@ -128,10 +121,9 @@ extern "C"
} else {
// buffer overflow?
// according to msdn this happens in message read mode only
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Buffer full - %i, bytes read: %i\n"), fd, nNumberOfBytesRead);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Buffer full - %p, bytes read: %i\n", handle, nNumberOfBytesRead);
}
// nNumberOfBytesRead can be 0 here for unknown reason (bug 269223)
nNumberOfBytesRead = nNumberOfBytesToRead;
}
@ -155,12 +147,9 @@ extern "C"
}
}
CloseHandle(overlapped.hEvent);
#ifdef DEBUG_MONITOR
#ifdef READ_REPORT
_stprintf(buffer, _T("End read %i - bytes read: %d\n"), fd, nBuffOffset);
OutputDebugStringW(buffer);
#endif
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR) && isTraceEnabled(CDT_TRACE_READ_REPORT)) {
cdtTrace(L"End read %p - bytes read: %d\n", handle, nBuffOffset);
}
return nBuffOffset; // This is a real full readed length
}
@ -171,16 +160,13 @@ extern "C"
Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_close0(JNIEnv *env, jobject proc, jobject channel) {
int rc;
HANDLE handle = channelToHandle(env, channel);
#ifdef DEBUG_MONITOR
_TCHAR buffer[1000];
_stprintf(buffer, _T("Close %i\n"), fd);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Close %p\n", handle);
}
rc = (CloseHandle(handle) ? 0 : -1);
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Closed %i\n"), fd);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Closed %p\n", handle);
}
return (rc ? GetLastError() : 0);
}
@ -235,16 +221,13 @@ extern "C"
Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_close0(JNIEnv *env, jobject proc, jobject channel) {
int rc;
HANDLE handle = channelToHandle(env, channel);
#ifdef DEBUG_MONITOR
_TCHAR buffer[1000];
_stprintf(buffer, _T("Close %i\n"), fd);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Close %p\n", handle);
}
FlushFileBuffers(handle);
rc = (CloseHandle(handle) ? 0 : -1);
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Closed %i\n"), fd);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Closed %p\n", handle);
}
return (rc ? GetLastError() : 0);
}

View file

@ -18,6 +18,8 @@
#include <jni.h>
#include <windows.h>
#include "util.h"
#include "org_eclipse_cdt_utils_spawner_Spawner.h"
extern void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg);
@ -92,16 +94,12 @@ int interruptProcess(int pid) {
}
}
#ifdef DEBUG_MONITOR
_TCHAR buffer[1000];
#endif
int rc = 0;
consoleHWND = NULL;
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Try to interrupt process %i\n"), pid);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Try to interrupt process %i\n", pid);
}
// Find console
EnumWindows(find_child_console, (LPARAM)pid);
@ -157,16 +155,12 @@ int interruptProcess(int pid) {
if (child_thread) {
AttachThreadInput(GetCurrentThreadId(), child_thread, FALSE);
}
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Sent Ctrl-C & Ctrl-Break to process %i\n"), pid);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Sent Ctrl-C & Ctrl-Break to process %i\n", pid);
}
}
#ifdef DEBUG_MONITOR
} else {
_stprintf(buffer, _T("Cannot find console for process %i\n"), pid);
OutputDebugStringW(buffer);
#endif
} else if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Cannot find console for process %i\n", pid);
}
return rc;

View file

@ -26,7 +26,8 @@
#include <psapi.h>
#include <stdbool.h>
//#define DEBUG_MONITOR
#include "util.h"
#define MAX_CMD_LINE_LENGTH (2049)
#define PIPE_NAME_LENGTH 100
@ -157,22 +158,22 @@ int main() {
int len = wcslen(argv[i]);
int requiredSize = nPos + len + 2;
if (requiredSize > 32 * 1024) {
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Command line too long!\n"));
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Command line too long!\n");
}
return 0;
}
ensureSize(&szCmdLine, &nCmdLineLength, requiredSize);
if (NULL == szCmdLine) {
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Not enough memory to build cmd line!\n"));
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Not enough memory to build cmd line!\n");
}
return 0;
}
if (0 > (nCpyLen = copyTo(szCmdLine + nPos, argv[i], len, nCmdLineLength - nPos))) {
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Not enough space to build command line\n"));
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Not enough space to build command line\n");
}
return 0;
}
nPos += nCpyLen;
@ -184,10 +185,6 @@ int main() {
STARTUPINFOW si = {sizeof(si)};
PROCESS_INFORMATION pi = {0};
DWORD dwExitCode = 0;
#ifdef DEBUG_MONITOR
int currentPID = GetCurrentProcessId();
wchar_t buffer[MAX_CMD_LINE_LENGTH];
#endif
BOOL exitProc = FALSE;
HANDLE waitEvent = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[4]);
@ -212,10 +209,9 @@ int main() {
nCounter);
swprintf(errPipeName, sizeof(errPipeName) / sizeof(errPipeName[0]), L"\\\\.\\pipe\\stderr%08i%010i", parentPid,
nCounter);
#ifdef DEBUG_MONITOR
swprintf(buffer, _T("Pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Pipes: %s, %s, %s\n", inPipeName, outPipeName, errPipeName);
}
HANDLE stdHandles[3];
@ -230,11 +226,11 @@ int main() {
(stdHandles[1] = CreateFileW(outPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa))) ||
(INVALID_HANDLE_VALUE ==
(stdHandles[2] = CreateFileW(errPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa)))) {
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Failed to open pipe %i, %i, %i: %i\n"), stdHandles[0],
stdHandles[1], stdHandles[2], GetLastError());
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Failed to open pipe %i, %i, %i: %i\n", stdHandles[0], stdHandles[1], stdHandles[2],
GetLastError());
}
CloseHandle(stdHandles[0]);
CloseHandle(stdHandles[1]);
CloseHandle(stdHandles[2]);
@ -246,40 +242,37 @@ int main() {
if (!SetStdHandle(STD_INPUT_HANDLE, stdHandles[0]) || !SetStdHandle(STD_OUTPUT_HANDLE, stdHandles[1]) ||
!SetStdHandle(STD_ERROR_HANDLE, stdHandles[2])) {
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Failed to reassign standard streams: %i\n"),
GetLastError());
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Failed to reassign standard streams: %i\n", GetLastError());
}
CloseHandle(stdHandles[0]);
CloseHandle(stdHandles[1]);
CloseHandle(stdHandles[2]);
return -1;
}
#ifdef DEBUG_MONITOR_DETAILS
wchar_t *lpvEnv = GetEnvironmentStringsW();
if (isTraceEnabled(CDT_TRACE_MONITOR_DETAILS)) {
wchar_t *lpvEnv = GetEnvironmentStringsW();
// If the returned pointer is NULL, exit.
if (lpvEnv == NULL) {
OutputDebugStringW(_T("Cannot Read Environment\n"));
} else {
// Variable strings are separated by NULL byte, and the block is
// terminated by a NULL byte.
// If the returned pointer is NULL, exit.
if (lpvEnv == NULL) {
cdtTrace(L"Cannot Read Environment\n");
} else {
// Variable strings are separated by NULL byte, and the block is
// terminated by a NULL byte.
OutputDebugStringW(_T("Starter: Environment\n"));
for (wchar_t *lpszVariable = (wchar_t *)lpvEnv; *lpszVariable; lpszVariable += wcslen(lpszVariable) + 1) {
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("%s\n"), lpszVariable);
OutputDebugStringW(buffer);
cdtTrace(L"Starter: Environment\n");
for (wchar_t *lpszVariable = lpvEnv; *lpszVariable; lpszVariable += wcslen(lpszVariable) + 1) {
cdtTrace(L"%s\n", lpszVariable);
}
FreeEnvironmentStringsW(lpvEnv);
}
FreeEnvironmentStringsW(lpvEnv);
}
#endif
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Starting: %s\n"), szCmdLine);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Starting: %s\n", szCmdLine);
}
// Create job object
HANDLE hJob = CreateJobObject(NULL, NULL);
if (hJob != NULL) {
@ -290,16 +283,14 @@ 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))) {
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Cannot set job information\n"));
DisplayErrorMessage();
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Cannot set job information\n");
DisplayErrorMessage();
}
}
} else {
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Cannot create job object\n"));
} else if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Cannot create job object\n");
DisplayErrorMessage();
#endif
}
// 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
@ -317,22 +308,19 @@ int main() {
CloseHandle(stdHandles[2]);
if (f) {
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Process %i started\n"), pi.dwProcessId);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Process %i started\n", pi.dwProcessId);
}
SetEvent(waitEvent); // Means that process has been spawned
CloseHandle(pi.hThread);
h[1] = pi.hProcess;
if (NULL != hJob) {
if (!AssignProcessToJobObject(hJob, pi.hProcess)) {
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Cannot assign process %i to a job\n"),
pi.dwProcessId);
OutputDebugStringW(buffer);
DisplayErrorMessage();
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Cannot assign process %i to a job\n", pi.dwProcessId);
DisplayErrorMessage();
}
}
}
@ -343,11 +331,9 @@ int main() {
switch (event) {
case WAIT_OBJECT_0 + 0: // SIGINT
case WAIT_OBJECT_0 + 4: // CTRL-C
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("starter (PID %i) received CTRL-C event\n"),
currentPID);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"starter (PID %i) received CTRL-C event\n", GetCurrentProcessId());
}
if ((event == (WAIT_OBJECT_0 + 0)) && isCygwin(h[1])) {
// Need to issue a kill command
wchar_t kill[1024];
@ -365,11 +351,9 @@ int main() {
case WAIT_OBJECT_0 + 1: // App terminated normally
// Make it's exit code our exit code
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]),
_T("starter: launched process has been terminated(PID %i)\n"), pi.dwProcessId);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"starter: launched process has been terminated(PID %i)\n", pi.dwProcessId);
}
GetExitCodeProcess(pi.hProcess, &dwExitCode);
exitProc = TRUE;
break;
@ -382,11 +366,9 @@ int main() {
case WAIT_OBJECT_0 + 3: // KILL
{
const wchar_t *signal = (event == WAIT_OBJECT_0 + 2) ? L"TERM" : L"KILL";
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("starter received %s event (PID %i)\n"), signal,
currentPID);
OutputDebugStringW(buffer);
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"starter received %s event (PID %i)\n", signal, GetCurrentProcessId());
}
if (isCygwin(h[1])) {
// Need to issue a kill command
wchar_t kill[1024];
@ -403,10 +385,10 @@ int main() {
if (NULL != hJob) {
if (!TerminateJobObject(hJob, (DWORD)-1)) {
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Cannot terminate job\n"));
DisplayErrorMessage();
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Cannot terminate job\n");
DisplayErrorMessage();
}
}
}
@ -416,20 +398,17 @@ int main() {
default:
// Unexpected code
#ifdef DEBUG_MONITOR
DisplayErrorMessage();
#endif
if (isTraceEnabled(CDT_TRACE_MONITOR)) {
DisplayErrorMessage();
}
exitProc = TRUE;
break;
}
}
} else {
#ifdef DEBUG_MONITOR
swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), _T("Cannot start: %s\n"), szCmdLine);
OutputDebugStringW(buffer);
} else if (isTraceEnabled(CDT_TRACE_MONITOR)) {
cdtTrace(L"Cannot start: %s\n", szCmdLine);
DisplayErrorMessage();
#endif
}
free(szCmdLine);

View file

@ -0,0 +1,75 @@
/*******************************************************************************
* Copyright (c) 2020 Torbjörn Svensson and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Torbjörn Svensson - initial API and implementation
*******************************************************************************/
#include "util.h"
#include <stdio.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;
}
switch (traceKind) {
case CDT_TRACE_MONITOR:
return monitor;
case CDT_TRACE_MONITOR_DETAILS:
return monitorDetails;
case CDT_TRACE_READ_REPORT:
return readReport;
default:
cdtTrace(L"Invalid trace kind supplied: %d\n", traceKind);
return false;
}
}
void cdtTrace(const wchar_t *fmt, ...) {
va_list ap;
wchar_t *buffer = NULL;
int size = 0;
va_start(ap, fmt);
do {
// Free previous buffer
free(buffer);
// Allocate a slightly larger buffer
size += 256;
buffer = (wchar_t *)malloc(size * sizeof(wchar_t));
if (!buffer) {
// malloc failed
OutputDebugStringW(L"Failed to allocate buffer to format message into.\n");
va_end(ap);
return;
}
} while (-1 == vswprintf(buffer, size, fmt, ap) && errno == ERANGE);
va_end(ap);
// Send the output
OutputDebugStringW(buffer);
// Clean up
free(buffer);
}

View file

@ -0,0 +1,26 @@
/*******************************************************************************
* Copyright (c) 2020 Torbjörn Svensson and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Torbjörn Svensson - initial API and implementation
*******************************************************************************/
#ifndef UTIL_H
#define UTIL_H
#include <stdbool.h>
#include <windows.h>
typedef enum { CDT_TRACE_MONITOR, CDT_TRACE_MONITOR_DETAILS, CDT_TRACE_READ_REPORT } TraceKind_t;
bool isTraceEnabled(const TraceKind_t traceKind);
void cdtTrace(const wchar_t *fmt, ...);
#endif /* UTIL_H */