Skip to content

Commit 53e5c03

Browse files
Adam Smithdscho
Adam Smith
authored andcommitted
exit_process.h: fix handling of SIGINT and SIGTERM
Handle SIGINT and SIGTERM by injecting into the process a thread that runs ExitProcess. Use TerminateProcess otherwise. In both cases, enumerate the entire process tree. This fixes git-for-windows/git#1219 Signed-off-by: Adam Smith <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 9f53930 commit 53e5c03

File tree

1 file changed

+56
-38
lines changed

1 file changed

+56
-38
lines changed

winsup/cygwin/include/cygwin/exit_process.h

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,56 @@
1414

1515
#include <tlhelp32.h>
1616

17+
static int
18+
terminate_process_with_remote_thread(HANDLE process, int exit_code)
19+
{
20+
static LPTHREAD_START_ROUTINE exit_process_address;
21+
if (!exit_process_address)
22+
{
23+
HINSTANCE kernel32 = GetModuleHandle ("kernel32");
24+
exit_process_address = (LPTHREAD_START_ROUTINE)
25+
GetProcAddress (kernel32, "ExitProcess");
26+
}
27+
DWORD thread_id;
28+
HANDLE thread = !exit_process_address ? NULL :
29+
CreateRemoteThread (process, NULL, 0, exit_process_address,
30+
(PVOID)exit_code, 0, &thread_id);
31+
32+
if (thread)
33+
{
34+
CloseHandle (thread);
35+
/*
36+
* Wait 10 seconds (arbitrary constant) for the process to
37+
* finish; After that grace period, fall back to terminating
38+
* non-gently.
39+
*/
40+
if (WaitForSingleObject (process, 10000) == WAIT_OBJECT_0)
41+
return 0;
42+
}
43+
44+
return -1;
45+
}
46+
1747
/**
18-
* Terminates the process corresponding to the process ID and all of its
19-
* directly and indirectly spawned subprocesses.
48+
* Terminates the process corresponding to the process ID
2049
*
21-
* This way of terminating the processes is not gentle: the processes get
22-
* no chance of cleaning up after themselves (closing file handles, removing
50+
* This way of terminating the processes is not gentle: the process gets
51+
* no chance of cleaning up after itself (closing file handles, removing
2352
* .lock files, terminating spawned processes (if any), etc).
2453
*/
2554
static int
26-
terminate_process_tree(HANDLE main_process, int exit_code)
55+
terminate_process(HANDLE process, int exit_code)
56+
{
57+
return int(TerminateProcess (process, exit_code));
58+
}
59+
60+
/**
61+
* Terminates the process corresponding to the process ID and all of its
62+
* directly and indirectly spawned subprocesses using the provided
63+
* terminate callback function
64+
*/
65+
static int
66+
terminate_process_tree(HANDLE main_process, int exit_code, int (*terminate)(HANDLE, int))
2767
{
2868
HANDLE snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
2969
PROCESSENTRY32 entry;
@@ -46,6 +86,7 @@ terminate_process_tree(HANDLE main_process, int exit_code)
4686
for (;;)
4787
{
4888
int orig_len = len;
89+
pid_t cyg_pid;
4990

5091
memset (&entry, 0, sizeof (entry));
5192
entry.dwSize = sizeof (entry);
@@ -57,6 +98,12 @@ terminate_process_tree(HANDLE main_process, int exit_code)
5798
{
5899
for (i = len - 1; i >= 0; i--)
59100
{
101+
cyg_pid = cygwin_winpid_to_pid(entry.th32ProcessID);
102+
if (cyg_pid > -1)
103+
{
104+
kill(cyg_pid, exit_code);
105+
continue;
106+
}
60107
if (pids[i] == entry.th32ProcessID)
61108
break;
62109
if (pids[i] == entry.th32ParentProcessID)
@@ -76,7 +123,7 @@ terminate_process_tree(HANDLE main_process, int exit_code)
76123

77124
if (process)
78125
{
79-
if (!TerminateProcess (process, exit_code))
126+
if (!(*terminate) (process, exit_code))
80127
ret = -1;
81128
CloseHandle (process);
82129
}
@@ -129,39 +176,10 @@ exit_process(HANDLE process, int exit_code)
129176

130177
if (GetExitCodeProcess (process, &code) && code == STILL_ACTIVE)
131178
{
132-
/*
133-
* We cannot determine the address of ExitProcess() for a process
134-
* that does not match the current architecture (e.g. for a 32-bit
135-
* process when we're running in 64-bit mode).
136-
*/
137-
if (process_architecture_matches_current (process))
138-
{
139-
static LPTHREAD_START_ROUTINE exit_process_address;
140-
if (!exit_process_address)
141-
{
142-
HINSTANCE kernel32 = GetModuleHandle ("kernel32");
143-
exit_process_address = (LPTHREAD_START_ROUTINE)
144-
GetProcAddress (kernel32, "ExitProcess");
145-
}
146-
DWORD thread_id;
147-
HANDLE thread = !exit_process_address ? NULL :
148-
CreateRemoteThread (process, NULL, 0, exit_process_address,
149-
(PVOID)exit_code, 0, &thread_id);
150-
151-
if (thread)
152-
{
153-
CloseHandle (thread);
154-
/*
155-
* Wait 10 seconds (arbitrary constant) for the process to
156-
* finish; After that grace period, fall back to terminating
157-
* non-gently.
158-
*/
159-
if (WaitForSingleObject (process, 10000) == WAIT_OBJECT_0)
160-
return 0;
161-
}
162-
}
179+
if (process_architecture_matches_current(process) && (exit_code == SIGINT || exit_code == SIGTERM))
180+
return terminate_process_tree (process, exit_code, terminate_process_with_remote_thread);
163181

164-
return terminate_process_tree (process, exit_code);
182+
return terminate_process_tree (process, exit_code, terminate_process);
165183
}
166184

167185
return -1;

0 commit comments

Comments
 (0)