Index: dmake/Makefile.am =================================================================== RCS file: /cvs/tools/dmake/Makefile.am,v retrieving revision 1.11 diff -u -r1.11 Makefile.am --- dmake/Makefile.am 18 Jan 2007 09:26:37 -0000 1.11 +++ dmake/Makefile.am 11 Nov 2007 22:27:51 -0000 @@ -61,7 +61,7 @@ if OSTYPEWIN32 dmake_SOURCES += win95/dchdir.c win95/switchar.c \ msdos/dstrlwr.c msdos/arlib.c \ - msdos/dirbrk.c msdos/runargv.c \ + msdos/dirbrk.c unix/runargv.c \ msdos/rmprq.c \ win95/microsft/ruletab.c INCLUDES += -I$(top_srcdir)/@OS_TYPE@/@OS_VERSION@ -I$(top_srcdir)/@OS_TYPE@ Index: dmake/Makefile.in =================================================================== RCS file: /cvs/tools/dmake/Makefile.in,v retrieving revision 1.14 diff -u -r1.14 Makefile.in --- dmake/Makefile.in 18 Jan 2007 09:26:49 -0000 1.14 +++ dmake/Makefile.in 11 Nov 2007 22:27:52 -0000 @@ -82,7 +82,7 @@ @OSTYPEWIN32_TRUE@am__append_4 = win95/dchdir.c win95/switchar.c \ @OSTYPEWIN32_TRUE@ msdos/dstrlwr.c msdos/arlib.c \ -@OSTYPEWIN32_TRUE@ msdos/dirbrk.c msdos/runargv.c \ +@OSTYPEWIN32_TRUE@ msdos/dirbrk.c unix/runargv.c \ @OSTYPEWIN32_TRUE@ msdos/rmprq.c \ @OSTYPEWIN32_TRUE@ win95/microsft/ruletab.c @@ -112,7 +112,7 @@ function.c dbug/dbug/dbug.c unix/arlib.c unix/dcache.c \ unix/dirbrk.c unix/rmprq.c unix/ruletab.c unix/runargv.c \ unix/tempnam.c win95/dchdir.c win95/switchar.c msdos/dstrlwr.c \ - msdos/arlib.c msdos/dirbrk.c msdos/runargv.c msdos/rmprq.c \ + msdos/arlib.c msdos/dirbrk.c msdos/rmprq.c \ win95/microsft/ruletab.c am__dirstamp = $(am__leading_dot)dirstamp @DBUG_TRUE@am__objects_1 = dbug/dbug/dbug.$(OBJEXT) @@ -124,8 +124,7 @@ @OSTYPEWIN32_TRUE@ win95/switchar.$(OBJEXT) \ @OSTYPEWIN32_TRUE@ msdos/dstrlwr.$(OBJEXT) \ @OSTYPEWIN32_TRUE@ msdos/arlib.$(OBJEXT) msdos/dirbrk.$(OBJEXT) \ -@OSTYPEWIN32_TRUE@ msdos/runargv.$(OBJEXT) \ -@OSTYPEWIN32_TRUE@ msdos/rmprq.$(OBJEXT) \ +@OSTYPEWIN32_TRUE@ unix/runargv.$(OBJEXT) msdos/rmprq.$(OBJEXT) \ @OSTYPEWIN32_TRUE@ win95/microsft/ruletab.$(OBJEXT) am_dmake_OBJECTS = infer.$(OBJEXT) make.$(OBJEXT) stat.$(OBJEXT) \ expand.$(OBJEXT) dmstring.$(OBJEXT) hash.$(OBJEXT) \ @@ -404,8 +403,6 @@ msdos/$(DEPDIR)/$(am__dirstamp) msdos/dirbrk.$(OBJEXT): msdos/$(am__dirstamp) \ msdos/$(DEPDIR)/$(am__dirstamp) -msdos/runargv.$(OBJEXT): msdos/$(am__dirstamp) \ - msdos/$(DEPDIR)/$(am__dirstamp) msdos/rmprq.$(OBJEXT): msdos/$(am__dirstamp) \ msdos/$(DEPDIR)/$(am__dirstamp) win95/microsft/$(am__dirstamp): @@ -427,7 +424,6 @@ -rm -f msdos/dirbrk.$(OBJEXT) -rm -f msdos/dstrlwr.$(OBJEXT) -rm -f msdos/rmprq.$(OBJEXT) - -rm -f msdos/runargv.$(OBJEXT) -rm -f unix/arlib.$(OBJEXT) -rm -f unix/dcache.$(OBJEXT) -rm -f unix/dirbrk.$(OBJEXT) @@ -467,7 +463,6 @@ @AMDEP_TRUE@@am__include@ @am__quote@msdos/$(DEPDIR)/dirbrk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msdos/$(DEPDIR)/dstrlwr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@msdos/$(DEPDIR)/rmprq.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@msdos/$(DEPDIR)/runargv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unix/$(DEPDIR)/arlib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unix/$(DEPDIR)/dcache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unix/$(DEPDIR)/dirbrk.Po@am__quote@ Index: dmake/dag.c =================================================================== RCS file: /cvs/tools/dmake/dag.c,v retrieving revision 1.11 diff -u -r1.11 dag.c --- dmake/dag.c 15 Oct 2007 15:38:09 -0000 1.11 +++ dmake/dag.c 11 Nov 2007 22:27:52 -0000 @@ -28,6 +28,10 @@ #include "extern.h" +#if defined(USE_CREATEPROCESS) +#include +#endif + static void set_macro_value(hp)/* @@ -86,6 +90,12 @@ if( hp->MV_IVAR == &Max_proc || hp->MV_IVAR == &Max_proclmt ) { if( tvalue < 1 ) Fatal( "Process limit value must be > 1" ); + +#if defined(USE_CREATEPROCESS) + if( Max_proclmt > MAXIMUM_WAIT_OBJECTS ) + Fatal( "Specified maximum # of processes (MAXPROCESSLIMIT)" + " exceeds OS limit of [%d].", MAXIMUM_WAIT_OBJECTS ); +#endif if( Max_proc > Max_proclmt ) Fatal( "Specified # of processes exceeds limit of [%d]", Index: dmake/dmake.c =================================================================== RCS file: /cvs/tools/dmake/dmake.c,v retrieving revision 1.12 diff -u -r1.12 dmake.c --- dmake/dmake.c 15 Oct 2007 15:38:21 -0000 1.12 +++ dmake/dmake.c 11 Nov 2007 22:27:52 -0000 @@ -146,6 +146,8 @@ /* Initialize Global variables to their default values */ Prolog(argc, argv); + /* Set internal macros to their initial values, some are changed + * later again by Make_rules() that parses the values from ruletab.c. */ Create_macro_vars(); Catch_signals(Quit); @@ -315,8 +317,9 @@ case 'P': if( p[1] ) { /* Only set MAXPROCESS if -S flag is *not* used. */ - if( !(Glob_attr & A_SEQ) ) + if( !(Glob_attr & A_SEQ) ) { Def_macro( "MAXPROCESS", p+1, M_MULTI|M_EXPANDED ); + } p += strlen(p)-1; } else @@ -337,6 +340,8 @@ } else if( (q = strchr(p, '=')) != NIL(char) ) { cmdmacs = DmStrAdd( cmdmacs, DmStrDup2(p), TRUE ); + /* Macros defined on the command line are marked precious. + * FIXME: The exception for += appears to be bogus. */ Parse_macro( p, (q[-1]!='+')?M_PRECIOUS:M_DEFAULT ); } else { Index: dmake/extern.h =================================================================== RCS file: /cvs/tools/dmake/extern.h,v retrieving revision 1.12.2.1 diff -u -r1.12.2.1 extern.h --- dmake/extern.h 11 Nov 2007 00:03:31 -0000 1.12.2.1 +++ dmake/extern.h 11 Nov 2007 22:27:52 -0000 @@ -139,6 +139,19 @@ # define NULLDEV "/dev/null" #endif +/* For MSVC 6.0 and newer and MinGW use the CreateProcess() function. */ +#if defined(__MINGW32__) || defined(_MSC_VER) && _MSC_VER >= 1200 +# define USE_CREATEPROCESS 1 +#else +/* #undef USE_CREATEPROCESS */ +#endif + +/* CreateProcess() is spawn-like. */ +#if ENABLE_SPAWN && ( HAVE_SPAWN_H || __CYGWIN__ || __EMX__) || defined(USE_CREATEPROCESS) +# define USE_SPAWN 1 +#else +/* #undef USE_SPAWN */ +#endif /* Work around some of the functions that may or may not exist */ #if ! HAVE_TZSET Index: dmake/imacs.c =================================================================== RCS file: /cvs/tools/dmake/imacs.c,v retrieving revision 1.8 diff -u -r1.8 imacs.c --- dmake/imacs.c 15 Oct 2007 15:39:37 -0000 1.8 +++ dmake/imacs.c 11 Nov 2007 22:27:53 -0000 @@ -28,6 +28,10 @@ #include "extern.h" +#if defined(USE_CREATEPROCESS) +#include +#endif + static void _set_int_var ANSI((char *, char *, int, int *)); static void _set_string_var ANSI((char *, char *, int, char **)); static void _set_bit_var ANSI((char *, char *, int)); @@ -137,9 +141,14 @@ _set_int_var( "PREP", "0", M_DEFAULT, &Prep ); (void) Def_macro("MAXLINELENGTH", "1024", M_FLAG | M_DEFAULT); - /* set MAXPROCESSLIMIT high initially so that it allows MAXPROCESS to - * change from command line. */ + /* MAXPROCESSLIMIT is overwritten by the ruletab.c settings. Set its + * initial value high so that it allows MAXPROCESS to be changed + * from the command line. */ _set_int_var( "MAXPROCESSLIMIT", "100", M_DEFAULT|M_NOEXPORT,&Max_proclmt ); +#if defined(USE_CREATEPROCESS) + /* Set the OS early enough. */ + Max_proclmt = MAXIMUM_WAIT_OBJECTS; +#endif _set_int_var( "MAXPROCESS", "1", M_DEFAULT|M_NOEXPORT, &Max_proc ); sprintf(buf,"%d",NAME_MAX); _set_int_var( "NAMEMAX", buf, M_DEFAULT|M_NOEXPORT, &NameMax); Index: dmake/sysintf.c =================================================================== RCS file: /cvs/tools/dmake/sysintf.c,v retrieving revision 1.12.2.1 diff -u -r1.12.2.1 sysintf.c --- dmake/sysintf.c 11 Nov 2007 00:19:15 -0000 1.12.2.1 +++ dmake/sysintf.c 11 Nov 2007 22:27:54 -0000 @@ -328,6 +328,7 @@ static char **av = NIL(char *); static int avs = 0; int i = 0; + char *s; /* Temporary string pointer. */ if( av == NIL(char *) ) { TALLOC(av, MINARGV, char*); @@ -345,12 +346,27 @@ if( shell && Shell_quote && *Shell_quote ) { /* Enclose the shell command with SHELLCMDQUOTE. */ - char *s; s = DmStrJoin(Shell_quote, *cmd, -1, FALSE); FREE(*cmd); *cmd = DmStrJoin(s, Shell_quote, -1, TRUE); } av[i++] = *cmd; + +#if defined(USE_CREATEPROCESS) + /* CreateProcess() needs one long command line. */ + av[0] = DmStrAdd(av[0], av[1], FALSE); + av[1] = NIL(char); + /* i == 3 means Shell_flags are given. */ + if( i == 3 ) { + s = av[0]; + av[0] = DmStrAdd(s, av[2], FALSE); + FREE(s); + av[2] = NIL(char); + } + /* The final free of cmd will free the concated command line. */ + FREE(*cmd); + *cmd = av[0]; +#endif av[i] = NIL(char); } else @@ -359,6 +375,14 @@ else { char *tcmd = *cmd; +#if defined(USE_CREATEPROCESS) + /* CreateProcess() needs one long command line, fill *cmd + * into av[0]. */ + while( iswhite(*tcmd) ) ++tcmd; + if( *tcmd ) av[i++] = tcmd; +#else + /* All other exec/spawn functions need the parameters separated + * in the argument vector. */ do { /* Fill *cmd into av[]. Whitespace is converted into '\0' to * terminate each av[] member. */ @@ -374,6 +398,7 @@ av = (char **) realloc( av, avs*sizeof(char *) ); } } while( *tcmd ); +#endif av[i] = NIL(char); } Index: dmake/msdos/runargv.c =================================================================== RCS file: /cvs/tools/dmake/msdos/runargv.c,v retrieving revision 1.5 diff -u -r1.5 runargv.c --- dmake/msdos/runargv.c 15 Oct 2007 15:43:15 -0000 1.5 +++ dmake/msdos/runargv.c 11 Nov 2007 22:27:54 -0000 @@ -23,6 +23,12 @@ -- Use cvs log to obtain detailed change logs. */ +#if defined(USE_CREATEPROCESS) +/* MSVC6.0 and newer and MinGW use the parallel build enabled runargv(). */ +Force a compile-time blowup. +This file should not be used, use unix/runargv.c instead. +#endif + #include #include #include "extern.h" Index: dmake/unix/runargv.c =================================================================== RCS file: /cvs/tools/dmake/unix/runargv.c,v retrieving revision 1.13.2.1 diff -u -r1.13.2.1 runargv.c --- dmake/unix/runargv.c 10 Nov 2007 01:54:08 -0000 1.13.2.1 +++ dmake/unix/runargv.c 11 Nov 2007 22:27:54 -0000 @@ -112,6 +112,10 @@ #include "extern.h" +#if defined(USE_CREATEPROCESS) +#include +#endif + #ifdef HAVE_WAIT_H # include #else @@ -148,9 +152,17 @@ struct prp *prp_next; } RCP, *RCPPTR; +#if defined(USE_CREATEPROCESS) + /* MS's HANDLE is basically a (void *) (winnt.h). */ +typedef HANDLE DMHANDLE; +#else +typedef int DMHANDLE; +#endif + typedef struct pr { int pr_valid; - int pr_pid; + DMHANDLE pr_pid; + DMHANDLE pr_tid; CELLPTR pr_target; int pr_ignore; int pr_last; @@ -160,17 +172,259 @@ char *pr_dir; } PR; +typedef struct tpid { + DMHANDLE pid; + DMHANDLE tid; +} TPID; + +const TPID NOPID = { (DMHANDLE)-1, (DMHANDLE)0 }; + static PR *_procs = NIL(PR); /* Array to hold concurrent processes. */ static int _procs_size = 0; /* Savegard to find MAXPROCESS changes. */ static int _proc_cnt = 0; /* Number of running processes. */ static int _abort_flg= FALSE; static int _use_i = -1; +#if defined(USE_CREATEPROCESS) +static HANDLE *_wpList = NIL(HANDLE); /* Array to hold pids to wait for. */ +#endif -static int _add_child ANSI((int, CELLPTR, int, int, int)); +static int _add_child ANSI((TPID, CELLPTR, int, int, int)); static void _attach_cmd ANSI((char *, int, CELLPTR, t_attr, int)); -static void _finished_child ANSI((int, int)); +static void _finished_child ANSI((DMHANDLE, int)); static int _running ANSI((CELLPTR)); +/* Machine/OS dependent helpers. */ +static DMHANDLE dmwaitnext ANSI((int *)); +static DMHANDLE dmwaitpid ANSI((int, int *)); + +#if defined( USE_SPAWN ) + +int terrno; /* Temporarily store errno. */ + +static TPID dmspawn ANSI((char **)); + +static TPID +dmspawn( argv ) + char **argv; +{ + TPID pid; + + /* No error output is done here as stdout/stderr might be redirected. */ +#if defined( __CYGWIN__) || defined( __EMX__) + pid.pid = spawnvp(_P_NOWAIT, argv[0], (const char**) argv); + pid.tid = 0; +#elif defined(USE_CREATEPROCESS) + static STARTUPINFO si; + static int initSTARTUPINFO = FALSE; + PROCESS_INFORMATION pi; + + /* si can be reused. */ + if( initSTARTUPINFO == FALSE ) { + initSTARTUPINFO = TRUE; + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + } + ZeroMemory( &pi, sizeof(pi) ); + + /* Start the child process. CreateProcess() parameters: + * No module name (use command line). + * Command line. This fails if the path to the program contains spaces. + * Process handle not inheritable. + * Thread handle not inheritable. + * Set handle inheritance to FALSE. + * No creation flags. + * Use parent's environment block. + * Use parent's starting directory. + * Pointer to STARTUPINFO structure. + * Pointer to PROCESS_INFORMATION structure. */ + if( CreateProcess(NULL, argv[0], NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) ) { + pid.pid = pi.hProcess; + pid.tid = pi.hThread; + } else { + printf( "CreateProcess failed (%d).\n", GetLastError() ); + pid.pid = (DMHANDLE)-1; + } +#else /* Non cygwin, OS/2, MinGW and MSC */ + int tpid; + if (posix_spawnp (&tpid, argv[0], NULL, NULL, argv, (char *)NULL)) + tpid = -1; /* posix_spawn failed */ + + pid.pid = tpid; + pid.tid = 0; +#endif /* __CYGWIN__ */ + return pid; +} + +#endif /* USE_SPAWN */ + +static DMHANDLE +dmwaitnext( status ) + int *status; + /* return pid we waited for, -1 if there + * was nothing to wait for (ECHILD) and -2 for other errors. */ +{ + DMHANDLE wid; +#if !defined(USE_CREATEPROCESS) + /* Here might be the culprit for the famous OOo build hang. If + * cygwin manages to "loose" a process and none else is left the + * wait() will wait forever. */ + wid = wait(status); + + /* If ECHILD is set from waitpid/wait then no child was left. */ + if( wid == -1 ) { + fprintf(stderr, "%s: Internal Error: wait() failed: %d - %s\n", + Pname, errno, strerror(errno) ); + if(errno != ECHILD) { + /* Wait was interrupted or a child was terminated (SIGCHLD) */ + return -2; + } else { + return -1; + } + } +#else + DWORD pEvent; + DWORD dwExitCode = 0; + + /* Create a list of possible objects to wait for. */ + int i; + int numProc = 0; + for( i=0; i= 0 && pEvent < WAIT_OBJECT_0 + numProc ) { + wid = _wpList[pEvent - WAIT_OBJECT_0]; + for( i=0; i force it, with exit code 1. */ + TerminateProcess(wid, 1); + dwExitCode = 1; + fprintf(stderr, "%s: Internal Error: Process still running - " + "terminate it!\n", Pname ); + } + + /* Close process and thread handles. */ + CloseHandle( wid ); + CloseHandle( _procs[i].pr_tid ); + } + else { + int err = GetLastError(); + LPVOID lpMsgBuf; + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + + fprintf(stderr, "%s: Internal Error: WaitForMultipleObjects() failed:" + " %d - %s\n", Pname, err, lpMsgBuf); + LocalFree(lpMsgBuf); + + /* No way to identify something comparable to ECHILD, always return -2.*/ + wid = (DMHANDLE)-2; + } + + + *status = dwExitCode; +#endif + return wid; +} + + +static DMHANDLE +dmwaitpid( pqid, status ) + int pqid; + int *status; + /* return pid we waited for, 0 if it didn't finish yet, -1 if there + * was nothing to wait for (ECHILD) and -2 for other errors. */ +{ + DMHANDLE wid; + +#if !defined(USE_CREATEPROCESS) + wid = waitpid(_procs[pqid].pr_pid, status, WNOHANG); + /* If ECHILD is set from waitpid/wait then no child was left. */ + if( wid == -1 ) { + fprintf(stderr, "%s: Internal Error: waitpid() failed: %d - %s\n", + Pname, errno, strerror(errno) ); + if(errno != ECHILD) { + /* Wait was interrupted or a child was terminated (SIGCHLD) */ + return -2; + } else { + return -1; + } + } +#else + DWORD pEvent; + DWORD dwExitCode = 0; + + /* Wait ... (Check status and return) */ + pEvent = WaitForSingleObject(_procs[pqid].pr_pid, 0); + + if( pEvent == WAIT_OBJECT_0 ) { + GetExitCodeProcess(_procs[pqid].pr_pid, &dwExitCode); + if(dwExitCode == STILL_ACTIVE) { + /* Process did not terminate -> force it, with exit code 1. */ + TerminateProcess(_procs[pqid].pr_pid, 1); + dwExitCode = 1; + fprintf(stderr, "%s: Internal Error: Process still running - " + "terminate it!\n", Pname ); + } + + /* Close process and thread handles. */ + CloseHandle( _procs[pqid].pr_pid ); + CloseHandle( _procs[pqid].pr_tid ); + } + else if( pEvent == WAIT_TIMEOUT ) { + wid = 0; + } + else { + int err = GetLastError(); + LPVOID lpMsgBuf; + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + + fprintf(stderr, "%s: Internal Error: WaitForSingleObject() failed:" + " %d - %s\n", Pname, err, lpMsgBuf); + LocalFree(lpMsgBuf); + + printf("pEvent:%d: %d %d\n", pEvent, WAIT_OBJECT_0, WAIT_TIMEOUT); + + exit(1); + + /* No way to identify something comparable to ECHILD, always return -2.*/ + wid = (DMHANDLE)-2; + } + + *status = dwExitCode; +#endif + + return wid; +} + + #if ! HAVE_STRERROR static char * private_strerror (errnum) @@ -211,7 +465,7 @@ int mute = (cmnd_attr & A_MUTE) != 0; /* Mute output ('@@'). */ int wfc = (cmnd_attr & A_WFC) != 0; /* Wait for completion. */ - int pid; + TPID pid; int st_pq = 0; /* Current _exec_shell target process index */ char *tcmd = *cmd; /* For saver/easier string arithmetic on *cmd. */ char **argv; @@ -300,8 +554,8 @@ } if ( internal ) { /* Use _add_child() / _finished_child() with internal command. */ - int cur_proc = _add_child(-1, target, ignore, last, FALSE); - _finished_child(-cur_proc, 0); + int cur_proc = _add_child(NOPID, target, ignore, last, FALSE); + _finished_child( (DMHANDLE)-cur_proc, 0 ); DB_RETURN( 0 ); } @@ -309,7 +563,7 @@ argv = Pack_argv( group, shell, cmd ); /* Really spawn or fork a child. */ -#if ENABLE_SPAWN && ( HAVE_SPAWN_H || __CYGWIN__ || __EMX__) +#if defined( USE_SPAWN ) /* As no other childs are started while the output is redirected this * is save. */ if( Is_exec_shell ) { @@ -326,23 +580,21 @@ dup2( zerofd, 1 ); } } -#if defined( __CYGWIN__) || defined( __EMX__) - pid = spawnvp(_P_NOWAIT, argv[0], (const char**) argv); -#else /* __CYGWIN__ */ - if (posix_spawnp (&pid, argv[0], NULL, NULL, argv, (char *)NULL)) - pid = -1; /* posix_spawn failed */ -#endif /* __CYGWIN__ */ + + pid = dmspawn( argv ); + terrno = errno; + if( old_stdout != -1 ) { dup2(old_stdout, 1); if( old_stderr != -1 ) dup2(old_stderr, 2); } - if(pid == -1) { + if(pid.pid == (DMHANDLE)-1) { /* spawn failed */ int cur_proc; fprintf(stderr, "%s: Error executing '%s': %s", - Pname, argv[0], strerror(errno) ); + Pname, argv[0], strerror(terrno) ); if( ignore||Continue ) { fprintf(stderr, " (Ignored)" ); } @@ -350,8 +602,8 @@ /* Use _add_child() / _finished_child() to treat the failure * gracefully, if so requested. */ - cur_proc = _add_child(-1, target, ignore, last, FALSE); - _finished_child(cur_proc, SIGTERM); + cur_proc = _add_child(NOPID, target, ignore, last, FALSE); + _finished_child((DMHANDLE)cur_proc, SIGTERM); /* _finished_child() aborts dmake if we are not told to * ignore errors. If we reach the this point return 0 as @@ -361,10 +613,10 @@ } else { _add_child(pid, target, ignore, last, wfc); } -#else /* ENABLE_SPAWN && ... */ +#else /* USE_SPAWN */ fflush(stdout); - switch( pid=fork() ){ + switch( pid.pid = fork() ){ case -1: /* fork failed */ Fatal("fork failed: %s: %s", argv[0], strerror( errno )); @@ -408,7 +660,7 @@ _add_child(pid, target, ignore, last, wfc); } -#endif /* ENABLE_SPAWN && ... */ +#endif /* USE_SPAWN */ DB_RETURN( 1 ); } @@ -429,8 +681,8 @@ int abort_flg; int pqid; { - int pid; - int wid; + DMHANDLE pid; + DMHANDLE wid; int status; /* Never wait for internal commands. */ int waitchild; @@ -452,7 +704,7 @@ if( i == Max_proc ) return(-1); - pid = -1; + pid = (DMHANDLE)-1; waitchild = FALSE; } else { @@ -477,34 +729,34 @@ do { /* Wait for the next process to finish. */ - if( (pid != -1) && (wid = waitpid(pid, &status, WNOHANG)) ) { + if( (pid != (DMHANDLE)-1) && (wid = dmwaitpid(pqid, &status)) ) { /* if wid is 0 this means that pid didn't finish yet. In this case * just handle the next finished process in the following "else". */ ; } else { - /* Here might be the culprit for the famous OOo build hang. If - * cygwin manages to "loose" a process and none else is left the - * wait() will wait forever. */ - wid = wait(&status); + wid = dmwaitnext(&status); /* If we get an error tell the error handling routine below that we * were not waiting for a specific pid. */ - if( wid == -1 ) - pid = -1; + if( wid == (DMHANDLE)-1 ) + pid = (DMHANDLE)-1; } /* If ECHILD is set from waitpid/wait then no child was left. */ - if( wid == -1 ) { - if(errno != ECHILD) { + if( (int)wid < 0 ) { /* Force int to check for sign. BRRR */ + if(wid == (DMHANDLE)-2) { /* Wait was interrupted or a child was terminated (SIGCHLD) */ if ( in_quit() ) { /* We're already terminating, just continue. */ return 0; } else { - Fatal( "dmake was interrupted or a child terminated: %d : %s - stopping all childs ...", errno, strerror( errno ) ); + Fatal( "dmake was interrupted or a child terminated. " + "Stopping all childs ..." ); } } else { - if( pid != -1 ) { + /* The child we were waiting for is missing or no child is + * left to wait for. */ + if( pid != (DMHANDLE)-1 ) { /* If we know the pid disable the pq entry. */ if( _procs[pqid].pr_valid ) { _procs[pqid].pr_valid = 0; @@ -564,11 +816,15 @@ if( _procs != NIL(PR) ) { for( i=0; i sizeof(DMHANDLE) ) + Fatal( "Internal Error: Check type of DMHANDLE!" ); +#endif } else { Fatal( "MAXPROCESS changed from `%d' to `%d' after a command was executed!", _procs_size, Max_proc ); @@ -624,7 +888,8 @@ pp = _procs+i; pp->pr_valid = 1; - pp->pr_pid = pid; + pp->pr_pid = pid.pid; + pp->pr_tid = pid.tid; pp->pr_target = target; pp->pr_ignore = ignore; pp->pr_last = last; @@ -636,11 +901,12 @@ _proc_cnt++; - if( pid != -1 ) { + if( pid.pid != (DMHANDLE)-1 ) { /* Wait for each recipe to finish if wfc is TRUE. This * basically forces sequential execution. */ - if( wfc ) + if( wfc ) { Wait_for_child( FALSE, i ); + } return -1; } else @@ -657,15 +923,15 @@ process and for cid < 1 -cid is used as the process array index of the internal command. */ -int cid; +DMHANDLE cid; int status; { register int i; char *dir; - if(cid < 1) { + if((int)cid < 1) { /* Force int. */ /* internal command */ - i = -cid; + i = -((int)cid); } else { for( i=0; i +#include "extern.h" + +#if defined(USE_CREATEPROCESS) +#include +#endif +#if !defined(MAXIMUM_WAIT_OBJECTS) +#define MAXIMUM_WAIT_OBJECTS 1 +#endif + +/* To stringify the result of the expansion of a macro argument + * use two levels of macros. */ +#define dmstr2(s) dmstr1(s) +#define dmstr1(s) #s static char *_rules[] = { "MAXLINELENGTH := 32766", - "MAXPROCESSLIMIT := 4", - "MAXPROCESS := 1", + "MAXPROCESSLIMIT := " dmstr2(MAXIMUM_WAIT_OBJECTS) , ".IMPORT .IGNORE: DMAKEROOT", ".MAKEFILES : makefile.mk makefile", ".SOURCE : .NULL",