From b237dff7753f444c4e0e8ea6bb1929243e45b310 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Mon, 8 Aug 2005 05:08:00 +0000 Subject: [PATCH] - Fixed a bug reported by Michael Matz regarding handling of parallel jobs after a failed job. - Enhancements to WINDOWS32 code from Eli Zaretskii. - Add Microsoft Project files from J. Grant. --- ChangeLog | 75 +++++++++ Makefile.am | 1 + README.W32.template | 16 +- build_w32.bat | 49 +++++- commands.c | 32 +++- doc/make.texi | 2 +- function.c | 6 +- job.c | 60 +++++-- main.c | 21 ++- make_msvc_net2003.sln | 21 +++ make_msvc_net2003.vcproj | 309 +++++++++++++++++++++++++++++++++++++ prepare_w32.bat | 1 + read.c | 23 ++- signame.c | 3 +- tests/ChangeLog | 6 + tests/scripts/features/parallelism | 27 ++++ w32/pathstuff.c | 4 +- w32/subproc/build.bat | 7 + w32/subproc/sub_proc.c | 26 +++- 19 files changed, 628 insertions(+), 61 deletions(-) create mode 100644 make_msvc_net2003.sln create mode 100644 make_msvc_net2003.vcproj diff --git a/ChangeLog b/ChangeLog index 2a22cbb..4d2c55b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,78 @@ +2005-08-07 Paul D. Smith + + * w32/pathstuff.c (getcwd_fs): Fix warning about assignment in a + conditional (slightly different version of a fix from Eli). + + Fix a bug reported by Michael Matz : patch included. + If make is running in parallel without -k and two jobs die in a + row, but not too close to each other, then make will quit without + waiting for the rest of the jobs to die. + + * main.c (die): Don't reset err before calling reap_children() the + second time: we still want it to be in the error condition. + * job.c (reap_children): Use a static variable, rather than err, + to control whether or not the error message should be printed. + +2005-08-06 Eli Zaretskii + + * w32/subproc/sub_proc.c: Include signal.h. + (process_pipe_io, process_file_io): Pass a pointer to a local + DWORD variable to GetExitCodeProcess. If the exit code is + CONTROL_C_EXIT, put SIGINT into pproc->signal. + + * job.c [WINDOWS32]: Include windows.h. + (main_thread) [WINDOWS32]: New global variable. + (reap_children) [WINDOWS32]: Get the handle for the main thread + and store it in main_thread. + + * commands.c [WINDOWS32]: Include windows.h and w32err.h. + (fatal_error_signal) [WINDOWS32]: Suspend the main thread before + doing anything else. When we are done, close the main thread + handle and exit with status 130. + +2005-07-30 Eli Zaretskii + + * w32/subproc/sub_proc.c (process_begin): Don't pass a NULL + pointer to fprintf. + + * main.c (find_and_set_default_shell): If found a DOSish shell, + set sh_found and the value of default_shell, and report the + findings in debug mode. + + * job.c (construct_command_argv_internal): Check unixy_shell, not + no_default_sh_exe, to decide whether to use Unixy or DOSish + builtin commands. + + * README.W32: Update with info about the MinGW build. + + * build_w32.bat: Support MinGW. + + * w32/subproc/build.bat: Likewise. + + * w32/subproc/sub_proc.c (process_easy): Fix format strings for + printing DWORD args. + + * function.c (windows32_openpipe): Fix format strings for printing + DWORD args. + + * job.c (reap_children) [WINDOWS32]: Don't declare 'status' and + 'reap_mode'. + (start_job_command): Fix format string for printing the result of + process_easy. + (start_job_command) [WINDOWS32]: Do not define. + (exec_command): Fix format string for printing HANDLE args. + + * main.c (handle_runtime_exceptions): Fix sprintf format strings + to avoid compiler warnings. + (open_tmpfile): Declare fd only if HAVE_FDOPEN is defined. + (Note: some of these fixes were submitted independently by J. Grant) + +2005-07-30 J. Grant + + * prepare_w32.bat: Copy config.h.w32 to config.h if not exist. + * make_msvc_net2003.vcproj, make_msvc_net2003.sln: MSVC Project files. + * Makefile.am (EXTRA_DIST): Add MSVC Project files. + 2005-07-08 Paul D. Smith * config.h.W32.template: Reorder to match the standard config.h, diff --git a/Makefile.am b/Makefile.am index c8c7cd4..96b3075 100644 --- a/Makefile.am +++ b/Makefile.am @@ -59,6 +59,7 @@ EXTRA_DIST = README build.sh.in $(man_MANS) \ README.Amiga Makefile.ami config.ami make.lnk amiga.c amiga.h \ README.DOS Makefile.DOS configure.bat dosbuild.bat configh.dos\ README.W32 NMakefile config.h.W32 build_w32.bat subproc.bat \ + make_msvc_net2003.sln make_msvc_net2003.vcproj \ readme.vms makefile.vms makefile.com config.h-vms \ vmsdir.h vmsfunctions.c vmsify.c diff --git a/README.W32.template b/README.W32.template index f034041..c9b7bfa 100644 --- a/README.W32.template +++ b/README.W32.template @@ -1,10 +1,22 @@ Port of GNU make to Microsoft Windows 95/98/NT/2000/XP Builds natively with MSVC 2.x, 4.x, 5.x, 6.x and MSVC.NET 7.x. +Also builds with the MinGW port of GCC 3.x (tested with GCC 3.4.2). The Windows 32-bit port of GNU make is maintained jointly by various -people. +people. It was originally made by Rob Tulloh. -To build with nmake on MS-Windows: +To build with MinGW: + + 1. Edit config.h.W32 to your liking (especially the few + shell-related defines near the end). + + 2. Invoke build_w32.bat with the "gcc" argument: + + build_w32 gcc + + This produces gnumake.exe in the current directory. + +To build with nmake: 1. Make sure cl.exe is in your %Path%. Example: diff --git a/build_w32.bat b/build_w32.bat index 95fdd8a..e0830f6 100644 --- a/build_w32.bat +++ b/build_w32.bat @@ -1,14 +1,14 @@ -set make=gnumake if not exist config.h copy config.h.W32 config.h cd w32\subproc -echo "Creating the subproc library" -%ComSpec% /c build.bat +@echo "Creating the subproc library" +%ComSpec% /c build.bat %1 cd ..\.. -del link.dbg link.rel -del config.h -copy config.h.W32 config.h -echo off -echo "Creating GNU make for Windows 95/NT" +@echo off +if exist link.dbg del link.dbg +if exist link.rel del link.rel +echo "Creating GNU Make for Windows 9X/NT/2K/XP" +if "%1" == "gcc" GoTo GCCBuild +set make=gnumake echo on if not exist .\WinDebug\nul mkdir .\WinDebug cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D TIVOLI /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c variable.c @@ -139,4 +139,37 @@ echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib sh link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe @link.rel if not exist .\WinRel/%make%.exe echo "WinRel build failed" if exist .\WinRel/%make%.exe echo "WinRel build succeeded!" +set make= +GoTo BuildEnd +:GCCBuild +echo on +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c variable.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c rule.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remote-stub.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c commands.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c file.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getloadavg.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c default.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c signame.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c expand.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c dir.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c main.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt1.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c job.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c read.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c version.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c arscan.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remake.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c hash.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c misc.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ar.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c function.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c vpath.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c implicit.c +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/glob.c -o glob.o +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/fnmatch.c -o fnmatch.o +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./w32/pathstuff.c -o pathstuff.o +gcc -mthreads -gstabs+ -ggdb3 -o gnumake.exe variable.o rule.o remote-stub.o commands.o file.o getloadavg.o default.o signame.o expand.o dir.o main.o getopt1.o job.o read.o version.o getopt.o arscan.o remake.o misc.o hash.o ar.o function.o vpath.o implicit.o glob.o fnmatch.o pathstuff.o w32_misc.o sub_proc.o w32err.o -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 +:BuildEnd echo on diff --git a/commands.c b/commands.c index 813610c..c70a009 100644 --- a/commands.c +++ b/commands.c @@ -23,6 +23,10 @@ Boston, MA 02111-1307, USA. */ #include "variable.h" #include "job.h" #include "commands.h" +#ifdef WINDOWS32 +#include +#include "w32err.h" +#endif #if VMS # define FILE_LIST_SEPARATOR ',' @@ -420,6 +424,27 @@ fatal_error_signal (int sig) exit (10); #else /* not Amiga */ +#ifdef WINDOWS32 + extern HANDLE main_thread; + + /* Windows creates a sperate 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 = %ld\n", susp_count); + else if (susp_count == (DWORD)-1) + { + DWORD ierr = GetLastError (); + + fprintf (stderr, "SuspendThread: error %ld: %s\n", + ierr, map_windows32_error_to_string (ierr)); + } + } +#endif handling_fatal_signal = 1; /* Set the handling for this signal to the default. @@ -482,8 +507,11 @@ fatal_error_signal (int sig) #endif #ifdef WINDOWS32 - /* Cannot call W32_kill with a pid (it needs a handle) */ - exit (EXIT_FAILURE); + 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); #else /* Signal the same code; this time it will really be fatal. The signal will be unblocked when we return and arrive then to kill us. */ diff --git a/doc/make.texi b/doc/make.texi index 32d1558..526aec6 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -5251,7 +5251,7 @@ definition of the variable. If you defined it first with @samp{:=}, making it a simply-expanded variable, @samp{+=} adds to that simply-expanded definition, and expands the new text before appending it to the old value just as @samp{:=} does -(@pxref{Setting, ,Setting Variables}, for a full explanation of @samp{:=}). +(@pxref{Setting, ,Setting Variables} for a full explanation of @samp{:=}). In fact, @example diff --git a/function.c b/function.c index 0772739..5bf6019 100644 --- a/function.c +++ b/function.c @@ -1329,7 +1329,7 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { - fatal (NILF, _("create_child_process: DuplicateHandle(In) failed (e=%d)\n"), + fatal (NILF, _("create_child_process: DuplicateHandle(In) failed (e=%ld)\n"), GetLastError()); } @@ -1340,12 +1340,12 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { - fatal (NILF, _("create_child_process: DuplicateHandle(Err) failed (e=%d)\n"), + fatal (NILF, _("create_child_process: DuplicateHandle(Err) failed (e=%ld)\n"), GetLastError()); } if (!CreatePipe(&hChildOutRd, &hChildOutWr, &saAttr, 0)) - fatal (NILF, _("CreatePipe() failed (e=%d)\n"), GetLastError()); + fatal (NILF, _("CreatePipe() failed (e=%ld)\n"), GetLastError()); hProcess = process_init_fd(hIn, hChildOutWr, hErr); diff --git a/job.c b/job.c index 1776aca..1f49175 100644 --- a/job.c +++ b/job.c @@ -33,10 +33,12 @@ Boston, MA 02111-1307, USA. */ /* Default shell to use. */ #ifdef WINDOWS32 +#include char *default_shell = "sh.exe"; int no_default_sh_exe = 1; int batch_mode_shell = 1; +HANDLE main_thread; #elif defined (_AMIGA) @@ -444,9 +446,11 @@ extern int shell_function_pid, shell_function_completed; void reap_children (int block, int err) { +#ifndef WINDOWS32 WAIT_T status; /* Initially, assume we have some. */ int reap_more = 1; +#endif #ifdef WAIT_NOHANG # define REAP_MORE reap_more @@ -475,9 +479,14 @@ reap_children (int block, int err) if (err && block) { - /* We might block for a while, so let the user know why. */ + static int printed = 0; + + /* We might block for a while, so let the user know why. + Only print this message once no matter how many jobs are left. */ fflush (stdout); - error (NILF, _("*** Waiting for unfinished jobs....")); + if (!printed) + error (NILF, _("*** Waiting for unfinished jobs....")); + printed = 1; } /* We have one less dead child to reap. As noted in @@ -608,23 +617,43 @@ reap_children (int block, int err) #ifdef WINDOWS32 { HANDLE hPID; - int err; + int werr; + HANDLE hcTID, hcPID; exit_code = 0; 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 = 0x%08lx\n", + (unsigned long)main_thread)); + } + /* wait for anything to finish */ hPID = process_wait_for_any(); if (hPID) { /* was an error found on this process? */ - err = process_last_err(hPID); + werr = process_last_err(hPID); /* get exit data */ exit_code = process_exit_code(hPID); - if (err) + if (werr) fprintf(stderr, "make (e=%d): %s", exit_code, map_windows32_error_to_string(exit_code)); @@ -937,7 +966,7 @@ set_child_handler_action_flags (int set_handler, int set_alarm) static void start_job_command (struct child *child) { -#ifndef _AMIGA +#if !defined(_AMIGA) && !defined(WINDOWS32) static int bad_stdin = -1; #endif register char *p; @@ -1351,7 +1380,7 @@ start_job_command (struct child *child) int i; unblock_sigs(); fprintf(stderr, - _("process_easy() failed failed to launch process (e=%d)\n"), + _("process_easy() failed failed to launch process (e=%ld)\n"), process_last_err(hPID)); for (i = 0; argv[i]; i++) fprintf(stderr, "%s ", argv[i]); @@ -1968,7 +1997,7 @@ exec_command (char **argv, char **envp) { int i; fprintf(stderr, - _("process_easy() failed failed to launch process (e=%d)\n"), + _("process_easy() failed failed to launch process (e=%ld)\n"), process_last_err(hPID)); for (i = 0; argv[i]; i++) fprintf(stderr, "%s ", argv[i]); @@ -2272,7 +2301,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell, #ifdef WINDOWS32 int slow_flag = 0; - if (no_default_sh_exe) { + if (!unixy_shell) { sh_cmds = sh_cmds_dos; sh_chars = sh_chars_dos; } else { @@ -2449,12 +2478,11 @@ construct_command_argv_internal (char *line, char **restp, char *shell, else if (p[1] != '\0') { #ifdef HAVE_DOS_PATHS - /* Only remove backslashes before characters special - to Unixy shells. All other backslashes are copied - verbatim, since they are probably DOS-style - directory separators. This still leaves a small - window for problems, but at least it should work - for the vast majority of naive users. */ + /* Only remove backslashes before characters special to Unixy + shells. All other backslashes are copied verbatim, since + they are probably DOS-style directory separators. This + still leaves a small window for problems, but at least it + should work for the vast majority of naive users. */ #ifdef __MSDOS__ /* A dot is only special as part of the "..." @@ -2469,7 +2497,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell, #endif if (p[1] != '\\' && p[1] != '\'' && !isspace ((unsigned char)p[1]) - && (strchr (sh_chars_sh, p[1]) == 0)) + && strchr (sh_chars_sh, p[1]) == 0) /* back up one notch, to copy the backslash */ --p; #endif /* HAVE_DOS_PATHS */ diff --git a/main.c b/main.c index 71e34a1..37c6ef6 100644 --- a/main.c +++ b/main.c @@ -662,14 +662,14 @@ handle_runtime_exceptions( struct _EXCEPTION_POINTERS *exinfo ) if (! ISDB (DB_VERBOSE)) { sprintf(errmsg, - _("%s: Interrupt/Exception caught (code = 0x%x, addr = 0x%x)\n"), + _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%lx)\n"), prg, exrec->ExceptionCode, exrec->ExceptionAddress); fprintf(stderr, errmsg); exit(255); } sprintf(errmsg, - _("\nUnhandled exception filter called from program %s\nExceptionCode = %x\nExceptionFlags = %x\nExceptionAddress = %x\n"), + _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = %lx\n"), prg, exrec->ExceptionCode, exrec->ExceptionFlags, exrec->ExceptionAddress); @@ -677,8 +677,8 @@ handle_runtime_exceptions( struct _EXCEPTION_POINTERS *exinfo ) && exrec->NumberParameters >= 2) sprintf(&errmsg[strlen(errmsg)], (exrec->ExceptionInformation[0] - ? _("Access violation: write operation at address %x\n") - : _("Access violation: read operation at address %x\n")), + ? _("Access violation: write operation at address %lx\n") + : _("Access violation: read operation at address %lx\n")), exrec->ExceptionInformation[1]); /* turn this on if we want to put stuff in the event log too */ @@ -751,7 +751,11 @@ find_and_set_default_shell (char *token) && !strcmpi (tokend - 4, "cmd.exe"))) { batch_mode_shell = 1; unixy_shell = 0; - sh_found = 0; + sprintf (sh_path, "%s", search_token); + default_shell = xstrdup (w32ify (sh_path, 0)); + DB (DB_VERBOSE, + (_("find_and_set_shell setting default_shell = %s\n"), default_shell)); + sh_found = 1; } else if (!no_default_sh_exe && (token == NULL || !strcmp (search_token, default_shell))) { /* no new information, path already set or known */ @@ -838,7 +842,9 @@ extern int mkstemp PARAMS ((char *template)); FILE * open_tmpfile(char **name, const char *template) { +#ifdef HAVE_FDOPEN int fd; +#endif #if defined HAVE_MKSTEMP || defined HAVE_MKTEMP # define TEMPLATE_LEN strlen (template) @@ -1217,7 +1223,7 @@ main (int argc, char **argv, char **envp) decode_switches (argc, argv, 0); #ifdef WINDOWS32 if (suspend_flag) { - fprintf(stderr, "%s (pid = %d)\n", argv[0], GetCurrentProcessId()); + fprintf(stderr, "%s (pid = %ld)\n", argv[0], GetCurrentProcessId()); fprintf(stderr, _("%s is suspending for 30 seconds..."), argv[0]); Sleep(30 * 1000); fprintf(stderr, _("done sleep(30). Continuing.\n")); @@ -2990,7 +2996,8 @@ die (int status) print_version (); /* Wait for children to die. */ - for (err = (status != 0); job_slots_used > 0; err = 0) + err = (status != 0); + while (job_slots_used > 0) reap_children (1, err); /* Let the remote job module clean up its state. */ diff --git a/make_msvc_net2003.sln b/make_msvc_net2003.sln new file mode 100644 index 0000000..e993896 --- /dev/null +++ b/make_msvc_net2003.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_msvc.net2003", "make_msvc_net2003.vcproj", "{E96B5060-3240-4723-91C9-E64F1C877A04}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {E96B5060-3240-4723-91C9-E64F1C877A04}.Debug.ActiveCfg = Debug|Win32 + {E96B5060-3240-4723-91C9-E64F1C877A04}.Debug.Build.0 = Debug|Win32 + {E96B5060-3240-4723-91C9-E64F1C877A04}.Release.ActiveCfg = Release|Win32 + {E96B5060-3240-4723-91C9-E64F1C877A04}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/make_msvc_net2003.vcproj b/make_msvc_net2003.vcproj new file mode 100644 index 0000000..fcf6ba8 --- /dev/null +++ b/make_msvc_net2003.vcproj @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/prepare_w32.bat b/prepare_w32.bat index e50e5f2..e16b784 100644 --- a/prepare_w32.bat +++ b/prepare_w32.bat @@ -1,5 +1,6 @@ @echo off @echo Windows32 CVS build preparation of config.h.W32 and NMakefile. if not exist config.h.W32 copy config.h.W32.template config.h.W32 +if not exist config.h copy config.h.W32 config.h if not exist NMakefile copy NMakefile.template NMakefile @echo Preparation complete. Run build_w32.bat to compile and link. diff --git a/read.c b/read.c index a6e18b0..65a352f 100644 --- a/read.c +++ b/read.c @@ -2064,22 +2064,19 @@ record_files (struct nameseq *filenames, char *pattern, char *pattern_percent, d_ptr = &(*d_ptr)->next; if (cmds != 0) - { - /* This is the rule with commands, so put its deps - last. The rationale behind this is that $< expands - to the first dep in the chain, and commands use $< - expecting to get the dep that rule specifies. - However the second expansion algorithm reverses - the order thus we need to make it last here. */ - - (*d_ptr)->next = this; - } + /* This is the rule with commands, so put its deps + last. The rationale behind this is that $< expands to + the first dep in the chain, and commands use $< + expecting to get the dep that rule specifies. However + the second expansion algorithm reverses the order thus + we need to make it last here. */ + (*d_ptr)->next = this; else { /* This is the rule without commands. Put its - dependencies at the end but before dependencies - from the rule with commands (if any). This way - everything appears in makefile order. */ + dependencies at the end but before dependencies from + the rule with commands (if any). This way everything + appears in makefile order. */ if (f->cmds != 0) { diff --git a/signame.c b/signame.c index c5583d2..1e2d57c 100644 --- a/signame.c +++ b/signame.c @@ -239,11 +239,12 @@ strsignal (int signal) # define sys_siglist _sys_siglist # elif HAVE_DECL___SYS_SIGLIST # define sys_siglist __sys_siglist -# endif +# else static char sig_initted = 0; if (!sig_initted) sig_initted = signame_init (); +# endif #endif if (signal > 0 || signal < NSIG) diff --git a/tests/ChangeLog b/tests/ChangeLog index ee3bab5..a205074 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2005-08-07 Paul D. Smith + + * scripts/features/parallelism: Add a test for a bug reported by + Michael Matz (matz@suse.de) in which make exits without waiting + for all its children in some situations during parallel builds. + 2005-07-08 Paul D. Smith * test_driver.pl: Reset the environment to a clean value every diff --git a/tests/scripts/features/parallelism b/tests/scripts/features/parallelism index 4768539..c75f436 100644 --- a/tests/scripts/features/parallelism +++ b/tests/scripts/features/parallelism @@ -83,4 +83,31 @@ all: first second first second: ; \@echo \$\@; $sleep_command 1; echo \$\@", '-j2', "first\nfirst\nsecond\nsecond"); +# Michael Matz reported a bug where if make is running in +# parallel without -k and two jobs die in a row, but not too close to each +# other, then make will quit without waiting for the rest of the jobs to die. + +run_make_test(" +.PHONY: all fail.1 fail.2 fail.3 ok +all: fail.1 ok fail.2 fail.3 + +fail.1 fail.2 fail.3: + \@sleep \$(patsubst fail.%,%,\$\@) + \@echo Fail + \@exit 1 + +ok: + \@sleep 4 + \@echo Ok done", + '-rR -j5', 'Fail +#MAKE#: *** [fail.1] Error 1 +#MAKE#: *** Waiting for unfinished jobs.... +Fail +#MAKE#: *** [fail.2] Error 1 +Fail +#MAKE#: *** [fail.3] Error 1 +Ok done', + 512); + + 1; diff --git a/w32/pathstuff.c b/w32/pathstuff.c index d8f3845..2ccb26d 100644 --- a/w32/pathstuff.c +++ b/w32/pathstuff.c @@ -86,9 +86,9 @@ w32ify(char *filename, int resolve) char * getcwd_fs(char* buf, int len) { - char *p; + char *p = getcwd(buf, len); - if (p = getcwd(buf, len)) { + if (p) { char *q = w32ify(buf, 0); strncpy(buf, q, len); } diff --git a/w32/subproc/build.bat b/w32/subproc/build.bat index b68fc31..b057b3c 100644 --- a/w32/subproc/build.bat +++ b/w32/subproc/build.bat @@ -1,3 +1,4 @@ +@if "%1" == "gcc" GoTo GCCBuild if not exist .\WinDebug\nul mkdir .\WinDebug cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c misc.c cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c @@ -8,3 +9,9 @@ cl.exe /nologo /MT /W4 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG cl.exe /nologo /MT /W4 /GX /YX /O2 /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c cl.exe /nologo /MT /W4 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c w32err.c lib.exe /NOLOGO /OUT:.\WinRel\subproc.lib .\WinRel/misc.obj .\WinRel/sub_proc.obj .\WinRel/w32err.obj +GoTo BuildEnd +:GCCBuild +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I.. -I. -I../include -I../.. -DWINDOWS32 -c misc.c -o ../../w32_misc.o +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I.. -I. -I../include -I../.. -DWINDOWS32 -c sub_proc.c -o ../../sub_proc.o +gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I.. -I. -I../include -I../.. -DWINDOWS32 -c w32err.c -o ../../w32err.o +:BuildEnd diff --git a/w32/subproc/sub_proc.c b/w32/subproc/sub_proc.c index 6e36e37..ae1a354 100644 --- a/w32/subproc/sub_proc.c +++ b/w32/subproc/sub_proc.c @@ -1,6 +1,7 @@ #include #include #include /* for msvc _beginthreadex, _endthreadex */ +#include #include #include "sub_proc.h" @@ -522,7 +523,8 @@ process_begin( pproc->last_err = GetLastError(); pproc->lerrno = E_FORK; - fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path, command_line); + fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", + exec_path ? exec_path : "NULL", command_line); if (envblk) free(envblk); free( command_line ); return(-1); @@ -762,7 +764,13 @@ process_pipe_io( } else if (ready_hand == childhand) { - GetExitCodeResult = GetExitCodeProcess(childhand, (DWORD*)&pproc->exit_code); + DWORD ierr; + GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); + if (ierr == CONTROL_C_EXIT) { + pproc->signal = SIGINT; + } else { + pproc->exit_code = ierr; + } if (GetExitCodeResult == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; @@ -811,6 +819,7 @@ process_file_io( HANDLE childhand; DWORD wait_return; BOOL GetExitCodeResult; + DWORD ierr; if (proc == NULL) pproc = process_wait_for_any_private(); @@ -854,7 +863,12 @@ process_file_io( goto done2; } - GetExitCodeResult = GetExitCodeProcess(childhand, (DWORD*)&pproc->exit_code); + GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); + if (ierr == CONTROL_C_EXIT) { + pproc->signal = SIGINT; + } else { + pproc->exit_code = ierr; + } if (GetExitCodeResult == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; @@ -1163,7 +1177,7 @@ process_easy( TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { fprintf(stderr, - "process_easy: DuplicateHandle(In) failed (e=%d)\n", + "process_easy: DuplicateHandle(In) failed (e=%ld)\n", GetLastError()); return INVALID_HANDLE_VALUE; } @@ -1175,7 +1189,7 @@ process_easy( TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { fprintf(stderr, - "process_easy: DuplicateHandle(Out) failed (e=%d)\n", + "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", GetLastError()); return INVALID_HANDLE_VALUE; } @@ -1187,7 +1201,7 @@ process_easy( TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { fprintf(stderr, - "process_easy: DuplicateHandle(Err) failed (e=%d)\n", + "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", GetLastError()); return INVALID_HANDLE_VALUE; } -- 2.7.4