Skip to content

Commit 3adeefc

Browse files
committed
trace2: collect platform-specific process information
Add optional platform-specific code to log information about the current process. On Windows, this includes whether git.exe is running under a debugger and information about the ancestors of the process. The purpose of this information is to help indicate if the process was launched interactively or in the background by an IDE, for example. Signed-off-by: Jeff Hostetler <[email protected]>
1 parent c849c28 commit 3adeefc

File tree

4 files changed

+120
-2
lines changed

4 files changed

+120
-2
lines changed

common-main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ int main(int argc, const char **argv)
3737

3838
trace2_initialize();
3939
trace2_cmd_start(argv);
40+
trace2_collect_process_info();
4041

4142
git_resolve_executable_dir(argv[0]);
4243

compat/win32/ancestry.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#include "../../cache.h"
2+
#include "../../json-writer.h"
3+
#include <Psapi.h>
4+
#include <tlHelp32.h>
5+
6+
/*
7+
* Find the process data for the given PID in the given snapshot
8+
* and update the PROCESSENTRY32 data.
9+
*/
10+
static int find_pid(DWORD pid, HANDLE hSnapshot, PROCESSENTRY32 *pe32)
11+
{
12+
pe32->dwSize = sizeof(PROCESSENTRY32);
13+
14+
if (Process32First(hSnapshot, pe32)) {
15+
do {
16+
if (pe32->th32ProcessID == pid)
17+
return 1;
18+
} while (Process32Next(hSnapshot, pe32));
19+
}
20+
return 0;
21+
}
22+
23+
/*
24+
* Accumulate JSON array:
25+
* [
26+
* exe-name-parent,
27+
* exe-name-grand-parent,
28+
* ...
29+
* ]
30+
*
31+
* Note: we only report the filename of the process executable; the
32+
* only way to get its full pathname is to use OpenProcess()
33+
* and GetModuleFileNameEx() or QueryfullProcessImageName()
34+
* and that seems rather expensive (on top of the cost of
35+
* getting the snapshot).
36+
*/
37+
static void get_processes(struct json_writer *jw, HANDLE hSnapshot)
38+
{
39+
PROCESSENTRY32 pe32;
40+
DWORD pid;
41+
42+
pid = GetCurrentProcessId();
43+
44+
/* We only want parent processes, so skip self. */
45+
if (!find_pid(pid, hSnapshot, &pe32))
46+
return;
47+
pid = pe32.th32ParentProcessID;
48+
49+
while (find_pid(pid, hSnapshot, &pe32)) {
50+
51+
jw_array_string(jw, pe32.szExeFile);
52+
53+
pid = pe32.th32ParentProcessID;
54+
}
55+
}
56+
57+
/*
58+
* Emit JSON data for the current and parent processes. Individual
59+
* trace2 targets can decide how to actually print it.
60+
*/
61+
static void get_ancestry(void)
62+
{
63+
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
64+
65+
if (hSnapshot != INVALID_HANDLE_VALUE) {
66+
struct json_writer jw = JSON_WRITER_INIT;
67+
68+
jw_array_begin(&jw, 0);
69+
get_processes(&jw, hSnapshot);
70+
jw_end(&jw);
71+
72+
trace2_data_json("process", the_repository,
73+
"windows/ancestry", &jw);
74+
75+
jw_release(&jw);
76+
CloseHandle(hSnapshot);
77+
}
78+
}
79+
80+
/*
81+
* Is a debugger attached to the current process?
82+
*
83+
* This will catch debug runs (where the debugger started the process).
84+
* This is the normal case. Since this code is called during our startup,
85+
* it will not report instances where a debugger is attached dynamically
86+
* to a running git process, but that is relatively rare.
87+
*/
88+
static void get_is_being_debugged(void)
89+
{
90+
if (IsDebuggerPresent())
91+
trace2_data_intmax("process", the_repository,
92+
"windows/debugger_present", 1);
93+
}
94+
95+
void trace2_collect_process_info(void)
96+
{
97+
if (!trace2_is_enabled())
98+
return;
99+
100+
get_is_being_debugged();
101+
get_ancestry();
102+
}

config.mak.uname

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,8 @@ ifeq ($(uname_S),Windows)
424424
BASIC_CFLAGS = -nologo -I. -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
425425
COMPAT_OBJS = compat/msvc.o compat/winansi.o \
426426
compat/win32/pthread.o compat/win32/syslog.o \
427-
compat/win32/dirent.o compat/win32/fscache.o
427+
compat/win32/dirent.o compat/win32/fscache.o \
428+
compat/win32/ancestry.o
428429
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
429430
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -ENTRY:wmainCRTStartup -SUBSYSTEM:CONSOLE
430431
# invalidcontinue.obj allows Git's source code to close the same file
@@ -586,7 +587,8 @@ ifneq (,$(findstring MINGW,$(uname_S)))
586587
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
587588
COMPAT_OBJS += compat/mingw.o compat/winansi.o \
588589
compat/win32/pthread.o compat/win32/syslog.o \
589-
compat/win32/dirent.o compat/win32/fscache.o
590+
compat/win32/dirent.o compat/win32/fscache.o \
591+
compat/win32/ancestry.o
590592
BASIC_CFLAGS += -DWIN32 -DPROTECT_NTFS_DEFAULT=1
591593
EXTLIBS += -lws2_32
592594
GITLIBS += git.res

trace2.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,4 +387,17 @@ __attribute__((format (printf, 1, 2)))
387387
void trace2_printf(const char *fmt, ...);
388388
#endif
389389

390+
/*
391+
* Optional platform-specific code to dump information about the
392+
* current and any parent process(es). This is intended to allow
393+
* post-processors to know who spawned this git instance and anything
394+
* else the platform may be able to tell us about the current process.
395+
*/
396+
#if defined(GIT_WINDOWS_NATIVE)
397+
void trace2_collect_process_info(void);
398+
#else
399+
#define trace2_collect_process_info() \
400+
do {} while (0)
401+
#endif
402+
390403
#endif /* TRACE2_H */

0 commit comments

Comments
 (0)