14
14
15
15
#include <tlhelp32.h>
16
16
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
+
17
47
/**
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
20
49
*
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
23
52
* .lock files, terminating spawned processes (if any), etc).
24
53
*/
25
54
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 ))
27
67
{
28
68
HANDLE snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS , 0 );
29
69
PROCESSENTRY32 entry ;
@@ -46,6 +86,7 @@ terminate_process_tree(HANDLE main_process, int exit_code)
46
86
for (;;)
47
87
{
48
88
int orig_len = len ;
89
+ pid_t cyg_pid ;
49
90
50
91
memset (& entry , 0 , sizeof (entry ));
51
92
entry .dwSize = sizeof (entry );
@@ -57,6 +98,12 @@ terminate_process_tree(HANDLE main_process, int exit_code)
57
98
{
58
99
for (i = len - 1 ; i >= 0 ; i -- )
59
100
{
101
+ cyg_pid = cygwin_winpid_to_pid (entry .th32ProcessID );
102
+ if (cyg_pid > -1 )
103
+ {
104
+ kill (cyg_pid , exit_code );
105
+ continue ;
106
+ }
60
107
if (pids [i ] == entry .th32ProcessID )
61
108
break ;
62
109
if (pids [i ] == entry .th32ParentProcessID )
@@ -76,7 +123,7 @@ terminate_process_tree(HANDLE main_process, int exit_code)
76
123
77
124
if (process )
78
125
{
79
- if (!TerminateProcess (process , exit_code ))
126
+ if (!( * terminate ) (process , exit_code ))
80
127
ret = -1 ;
81
128
CloseHandle (process );
82
129
}
@@ -129,39 +176,10 @@ exit_process(HANDLE process, int exit_code)
129
176
130
177
if (GetExitCodeProcess (process , & code ) && code == STILL_ACTIVE )
131
178
{
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 );
163
181
164
- return terminate_process_tree (process , exit_code );
182
+ return terminate_process_tree (process , exit_code , terminate_process );
165
183
}
166
184
167
185
return -1 ;
0 commit comments