--- 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