diff --git a/common-main.c b/common-main.c index 6dbdc4adf272ef..d484aec20979ac 100644 --- a/common-main.c +++ b/common-main.c @@ -37,6 +37,7 @@ int main(int argc, const char **argv) trace2_initialize(); trace2_cmd_start(argv); + trace2_collect_process_info(); git_resolve_executable_dir(argv[0]); diff --git a/compat/win32/trace2_win32_process_info.c b/compat/win32/trace2_win32_process_info.c new file mode 100644 index 00000000000000..253199f8121cae --- /dev/null +++ b/compat/win32/trace2_win32_process_info.c @@ -0,0 +1,101 @@ +#include "../../cache.h" +#include "../../json-writer.h" +#include +#include + +/* + * Find the process data for the given PID in the given snapshot + * and update the PROCESSENTRY32 data. + */ +static int find_pid(DWORD pid, HANDLE hSnapshot, PROCESSENTRY32 *pe32) +{ + pe32->dwSize = sizeof(PROCESSENTRY32); + + if (Process32First(hSnapshot, pe32)) { + do { + if (pe32->th32ProcessID == pid) + return 1; + } while (Process32Next(hSnapshot, pe32)); + } + return 0; +} + +/* + * Accumulate JSON array: + * [ + * exe-name-parent, + * exe-name-grand-parent, + * ... + * ] + * + * Note: we only report the filename of the process executable; the + * only way to get its full pathname is to use OpenProcess() + * and GetModuleFileNameEx() or QueryfullProcessImageName() + * and that seems rather expensive (on top of the cost of + * getting the snapshot). + */ +static void get_processes(struct json_writer *jw, HANDLE hSnapshot) +{ + PROCESSENTRY32 pe32; + DWORD pid; + + pid = GetCurrentProcessId(); + + /* We only want parent processes, so skip self. */ + if (!find_pid(pid, hSnapshot, &pe32)) + return; + pid = pe32.th32ParentProcessID; + + while (find_pid(pid, hSnapshot, &pe32)) { + jw_array_string(jw, pe32.szExeFile); + + pid = pe32.th32ParentProcessID; + } +} + +/* + * Emit JSON data for the current and parent processes. Individual + * trace2 targets can decide how to actually print it. + */ +static void get_ancestry(void) +{ + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + + if (hSnapshot != INVALID_HANDLE_VALUE) { + struct json_writer jw = JSON_WRITER_INIT; + + jw_array_begin(&jw, 0); + get_processes(&jw, hSnapshot); + jw_end(&jw); + + trace2_data_json("process", the_repository, "windows/ancestry", + &jw); + + jw_release(&jw); + CloseHandle(hSnapshot); + } +} + +/* + * Is a debugger attached to the current process? + * + * This will catch debug runs (where the debugger started the process). + * This is the normal case. Since this code is called during our startup, + * it will not report instances where a debugger is attached dynamically + * to a running git process, but that is relatively rare. + */ +static void get_is_being_debugged(void) +{ + if (IsDebuggerPresent()) + trace2_data_intmax("process", the_repository, + "windows/debugger_present", 1); +} + +void trace2_collect_process_info(void) +{ + if (!trace2_is_enabled()) + return; + + get_is_being_debugged(); + get_ancestry(); +} diff --git a/config.mak.uname b/config.mak.uname index c329b2d1204095..1bffbe530ce532 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -424,6 +424,7 @@ ifeq ($(uname_S),Windows) BASIC_CFLAGS = -nologo -I. -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE COMPAT_OBJS = compat/msvc.o compat/winansi.o \ compat/win32/pthread.o compat/win32/syslog.o \ + compat/win32/trace2_win32_process_info.o \ compat/win32/dirent.o compat/win32/fscache.o COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\" BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -ENTRY:wmainCRTStartup -SUBSYSTEM:CONSOLE @@ -585,6 +586,7 @@ ifneq (,$(findstring MINGW,$(uname_S))) COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32 COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" COMPAT_OBJS += compat/mingw.o compat/winansi.o \ + compat/win32/trace2_win32_process_info.o \ compat/win32/pthread.o compat/win32/syslog.o \ compat/win32/dirent.o compat/win32/fscache.o BASIC_CFLAGS += -DWIN32 -DPROTECT_NTFS_DEFAULT=1 diff --git a/trace2.h b/trace2.h index fce9891f534e04..ae5020d0e66e08 100644 --- a/trace2.h +++ b/trace2.h @@ -368,4 +368,18 @@ void trace2_printf(const char *fmt, ...); /* clang-format on */ #endif +/* + * Optional platform-specific code to dump information about the + * current and any parent process(es). This is intended to allow + * post-processors to know who spawned this git instance and anything + * else the platform may be able to tell us about the current process. + */ +#if defined(GIT_WINDOWS_NATIVE) +void trace2_collect_process_info(void); +#else +#define trace2_collect_process_info() \ + do { \ + } while (0) +#endif + #endif /* TRACE2_H */