-
Notifications
You must be signed in to change notification settings - Fork 7
/
make-4.4.1-win32-ctrl-c.patch
248 lines (231 loc) · 7.2 KB
/
make-4.4.1-win32-ctrl-c.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
--- make-4.4.1-orig/src/commands.c 2023-01-28 16:34:37.000000000 +0300
+++ make-4.4.1/src/commands.c 2024-09-18 08:19:25.692332500 +0300
@@ -472,6 +472,12 @@
/* Start the commands running. */
new_job (file);
}
+
+#ifdef WINDOWS32
+/* defined in job.c */
+extern void wait_until_main_thread_sleeps (void);
+#endif
+
/* This is set while we are inside fatal_error_signal,
so things can avoid nonreentrant operations. */
@@ -503,25 +509,12 @@
exit (10);
#else /* not Amiga */
#ifdef WINDOWS32
- extern HANDLE main_thread;
-
/* Windows creates a separate thread for handling Ctrl+C, so we need
to suspend the main thread, or else we will have race conditions
when both threads call reap_children. */
- if (main_thread)
- {
- DWORD susp_count = SuspendThread (main_thread);
- if (susp_count != 0)
- fprintf (stderr, "SuspendThread: suspend count = %lu\n", susp_count);
- else if (susp_count == (DWORD)-1)
- {
- DWORD ierr = GetLastError ();
-
- fprintf (stderr, "SuspendThread: error %lu: %s\n",
- ierr, map_windows32_error_to_string (ierr));
- }
- }
+ /* Wait until main thread releases resources and goes to sleep. */
+ wait_until_main_thread_sleeps ();
#endif
handling_fatal_signal = 1;
@@ -589,8 +582,6 @@
#endif
#ifdef WINDOWS32
- if (main_thread)
- CloseHandle (main_thread);
/* Cannot call W32_kill with a pid (it needs a handle). The exit
status of 130 emulates what happens in Bash. */
exit (130);
--- make-4.4.1-orig/src/job.c 2023-02-22 04:53:48.000000000 +0300
+++ make-4.4.1/src/job.c 2024-09-18 08:22:52.069933500 +0300
@@ -35,7 +35,6 @@
const char *default_shell = "sh.exe";
int no_default_sh_exe = 1;
int batch_mode_shell = 1;
-HANDLE main_thread;
#elif defined (_AMIGA)
@@ -620,6 +619,77 @@
#endif
}
+#ifdef WINDOWS32
+
+/* If non-zero, then Main thread should release resources and go to sleep. */
+int main_thread_should_sleep = 0;
+
+/* Event object on which Ctrl-C handler thread will wait
+ until Main thread unlocks resources. */
+static HANDLE susp_main_event = NULL;
+
+void create_susp_main_event (void)
+{
+ susp_main_event = CreateEvent(
+ NULL, /* The handle cannot be inherited by child processes */
+ FALSE, /* Manual-reset */
+ FALSE, /* Initial state */
+ NULL /* Name of the event object */
+ );
+
+ if (susp_main_event == NULL)
+ {
+ DWORD e = GetLastError ();
+ fprintf (stderr,
+ "Failed to create event object (Error %ld: %s)\n",
+ e, map_windows32_error_to_string (e));
+ }
+}
+
+void delete_susp_main_event (void)
+{
+ CloseHandle(susp_main_event);
+}
+
+/* If Main thread needs to be suspended, by calling this function, it
+ will wakeup Ctrl-C handler thread and then will go to infinite sleep. */
+static void check_need_sleep (void)
+{
+ /* Ctrl-C handler thread sets this flag only after suspending Main thread,
+ so if flag is set, then calling thread is not the Main thread. */
+ if (handling_fatal_signal)
+ return;
+
+ /* Check if Ctrl-C handler thread waits to suspend main thread. */
+ if (main_thread_should_sleep)
+ {
+ SetEvent (susp_main_event);
+ Sleep (INFINITE);
+ }
+}
+
+/* Called by Ctrl-C handler thread:
+ wait until main thread releases resources and goes to sleep. */
+void wait_until_main_thread_sleeps (void)
+{
+ DWORD result;
+
+ /* Tell Main thread that it should go to sleep. */
+ main_thread_should_sleep = 1;
+
+ /* And wait for it */
+ result = WaitForSingleObject(susp_main_event, INFINITE);
+ if (WAIT_OBJECT_0 != result)
+ {
+ DWORD e = GetLastError ();
+ fprintf (stderr,
+ "Failed to wait to suspend main thread (Error %ld: %s)\n",
+ e, map_windows32_error_to_string (e));
+ }
+}
+
+#endif /* WINDOWS32 */
+
extern pid_t shell_function_pid;
/* Reap all dead children, storing the returned status and the new command
@@ -663,6 +733,11 @@
int any_remote, any_local;
int dontcare;
+#ifdef WINDOWS32
+ /* Check if Main thread should go to sleep. */
+ check_need_sleep ();
+#endif
+
if (err && block)
{
static int printed = 0;
@@ -826,24 +901,6 @@
exit_sig = 0;
coredump = 0;
- /* Record the thread ID of the main process, so that we
- could suspend it in the signal handler. */
- if (!main_thread)
- {
- hcTID = GetCurrentThread ();
- hcPID = GetCurrentProcess ();
- if (!DuplicateHandle (hcPID, hcTID, hcPID, &main_thread, 0,
- FALSE, DUPLICATE_SAME_ACCESS))
- {
- DWORD e = GetLastError ();
- fprintf (stderr,
- "Determine main thread ID (Error %ld: %s)\n",
- e, map_windows32_error_to_string (e));
- }
- else
- DB (DB_VERBOSE, ("Main thread handle = %p\n", main_thread));
- }
-
/* wait for anything to finish */
hPID = process_wait_for_any (block, &dwWaitStatus);
if (hPID)
@@ -1010,7 +1067,13 @@
/* If there are more commands to run, try to start them. */
if (job_next_command (c))
{
- if (handling_fatal_signal)
+ int dying = handling_fatal_signal;
+#ifdef WINDOWS32
+ /* Check if Ctrl-C handler thread waits to kill jobs. */
+ if (main_thread_should_sleep)
+ dying = 1;
+#endif
+ if (dying)
{
/* Never start new commands while we are dying.
Since there are more commands that wanted to be run,
--- make-4.4.1-orig/src/main.c 2023-02-21 08:03:51.000000000 +0300
+++ make-4.4.1/src/main.c 2024-09-18 08:53:02.804603700 +0300
@@ -241,6 +241,12 @@
static char *shuffle_mode = NULL;
+#ifdef WINDOWS32
+/* defined in job.c */
+extern void create_susp_main_event (void);
+extern void delete_susp_main_event (void);
+#endif
+
/* Handle for the mutex to synchronize output of our children under -O. */
static char *sync_mutex = NULL;
@@ -1183,6 +1210,7 @@
const char *windows32_path = NULL;
SetUnhandledExceptionFilter (handle_runtime_exceptions);
+ create_susp_main_event ();
/* start off assuming we have no shell */
unixy_shell = 0;
@@ -3863,6 +3892,10 @@
int _x UNUSED;
_x = chdir (directory_before_chdir);
}
+
+#ifdef WINDOWS32
+ delete_susp_main_event ();
+#endif
}
exit (status);
--- make-4.4.1-orig/src/output.c 2023-01-02 01:05:12.000000000 +0300
+++ make-4.4.1/src/output.c 2024-09-18 08:28:02.662720300 +0300
@@ -176,6 +176,19 @@
break;
}
fflush (to);
+#ifdef WINDOWS32
+ /* Check if Make was interrupted. */
+ {
+ extern int main_thread_should_sleep;
+ if (main_thread_should_sleep)
+ {
+ /* If output is not redirected to file - stop writing,
+ because writing to windows console is too slow. */
+ if (-1l == ftell (to))
+ break;
+ }
+ }
+#endif
}
#ifdef WINDOWS32