Parcourir la source

Fix for it to compile on "all" windows platforms...

Andy Cedilnik il y a 23 ans
Parent
commit
375c695ba1
2 fichiers modifiés avec 156 ajouts et 39 suppressions
  1. 107 30
      Source/cmWin32ProcessExecution.cxx
  2. 49 9
      Source/cmWin32ProcessExecution.h

+ 107 - 30
Source/cmWin32ProcessExecution.cxx

@@ -25,6 +25,19 @@
 #include <sys/stat.h>
 #include <windows.h>
 
+#if defined(__BORLANDC__)
+#  define STRICMP stricmp
+#  define TO_INTPTR(x) ((long)(x))
+#else // Visual studio
+#  if ( _MSC_VER >= 1300 )
+#    include <stddef.h>
+#    define TO_INTPTR(x) ((intptr_t)(x))
+#  else // Visual Studio 6
+#    define TO_INTPTR(x) ((long)(x))
+#  endif // Visual studio .NET
+#  define STRICMP _stricmp
+#endif // Borland
+
 #define POPEN_1 1
 #define POPEN_2 2
 #define POPEN_3 3
@@ -34,6 +47,7 @@
 
 #define win32_error(x,y) std::cout << "Win32_Error(" << x << ", " << y << ")" << std::endl, false
 
+
 bool cmWin32ProcessExecution::StartProcess(
   const char* cmd, const char* path, bool verbose)
 {
@@ -47,6 +61,25 @@ bool cmWin32ProcessExecution::Wait(int timeout)
   return this->PrivateClose(timeout);
 }
 
+#define PERROR(str) //::ErrorMessage(__LINE__, str)
+static void ErrorMessage(int line, char *str)  //display detailed error info
+{
+  DWORD lastmsg = GetLastError();
+  LPVOID msg;
+  FormatMessage(
+    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+    NULL,
+    lastmsg,
+    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+    (LPTSTR) &msg,
+    0,
+    NULL
+  );
+  printf("%d - %s: %s (%d)\n",line,str,msg, lastmsg);
+  LocalFree(msg);
+  ::SetLastError(ERROR_SUCCESS);
+}
+
 /*
  * Internal dictionary mapping popen* file pointers to process handles,
  * for use when retrieving the process exit code.  See _PyPclose() below
@@ -62,19 +95,27 @@ static BOOL RealPopenCreateProcess(const char *cmdstring,
 				   HANDLE hStderr,
 				   HANDLE *hProcess)
 {
+  PERROR("Start");
+  //std::cout << "Run: " << cmdstring << std::endl;
+  PERROR("Start");
   PROCESS_INFORMATION piProcInfo;
+  PERROR("PROCESS_INFORMATION");
   STARTUPINFO siStartInfo;
+  PERROR("STARTUPINFO");
   char *s1,*s2, *s3 = " /c ";
   int i;
   int x;
-
   if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) 
     {
+    PERROR("GetEnvironmentVariable");
     char *comshell;
 
     s1 = (char *)_alloca(i);
     if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
+      {
+      PERROR("GetEnvironmentVariable");
       return x;
+      }
 
     /* Explicitly check if we are using COMMAND.COM.  If we are
      * then use the w9xpopen hack.
@@ -85,7 +126,7 @@ static BOOL RealPopenCreateProcess(const char *cmdstring,
     ++comshell;
 
     if (GetVersion() < 0x80000000 &&
-	_stricmp(comshell, "command.com") != 0) 
+	STRICMP(comshell, "command.com") != 0) 
       {
       /* NT/2000 and not using command.com. */
       x = i + (int)strlen(s3) + (int)strlen(cmdstring) + 1;
@@ -187,11 +228,13 @@ static BOOL RealPopenCreateProcess(const char *cmdstring,
 		    &siStartInfo,
 		    &piProcInfo) ) 
     {
+    PERROR("CreateProcess");
     /* Close the handles now so anyone waiting is woken. */
     CloseHandle(piProcInfo.hThread);
-
+    PERROR("Close Handle");
     /* Return process handle */
     *hProcess = piProcInfo.hProcess;
+    //std::cout << "Process created..." << std::endl;
     return TRUE;
     }
   win32_error("CreateProcess", s2);
@@ -212,7 +255,7 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
   SECURITY_ATTRIBUTES saAttr;
   BOOL fSuccess;
   int fd1, fd2, fd3;
-  FILE *f1, *f2, *f3;
+  //FILE *f1, *f2, *f3;
   long file_count;
 
   saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
@@ -220,8 +263,11 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
   saAttr.lpSecurityDescriptor = NULL;
 
   if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
+    {
     return win32_error("CreatePipe", NULL);
-
+    }
+  PERROR("CreatePipe");
+    
   /* Create new output read handle and the input write handle. Set
    * the inheritance properties to FALSE. Otherwise, the child inherits
    * the these handles; resulting in non-closeable handles to the pipes
@@ -232,10 +278,13 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
 			     DUPLICATE_SAME_ACCESS);
   if (!fSuccess)
     return win32_error("DuplicateHandle", NULL);
+  PERROR("DuplicateHandle");
+
 
   /* Close the inheritable version of ChildStdin
      that we're using. */
   CloseHandle(hChildStdinWr);
+  PERROR("CloseHandle");
 
   if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
     return win32_error("CreatePipe", NULL);
@@ -245,24 +294,29 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
 			     FALSE, DUPLICATE_SAME_ACCESS);
   if (!fSuccess)
     return win32_error("DuplicateHandle", NULL);
+  PERROR("DuplicateHandle");
 
   /* Close the inheritable version of ChildStdout
      that we're using. */
   CloseHandle(hChildStdoutRd);
+  PERROR("CloseHandle");
 
   if (n != POPEN_4) 
     {
     if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
       return win32_error("CreatePipe", NULL);
-    fSuccess = DuplicateHandle(GetCurrentProcess(),
+   PERROR("CreatePipe");
+   fSuccess = DuplicateHandle(GetCurrentProcess(),
 			       hChildStderrRd,
 			       GetCurrentProcess(),
 			       &hChildStderrRdDup, 0,
 			       FALSE, DUPLICATE_SAME_ACCESS);
     if (!fSuccess)
       return win32_error("DuplicateHandle", NULL);
+    PERROR("DuplicateHandle");
     /* Close the inheritable version of ChildStdErr that we're using. */
     CloseHandle(hChildStderrRd);
+    PERROR("CloseHandle");
     }
 	  
   switch (n) 
@@ -272,43 +326,47 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
 	{
 	case _O_WRONLY | _O_TEXT:
 	  /* Case for writing to child Stdin in text mode. */
-	  fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode);
-	  f1 = _fdopen(fd1, "w");
+	  fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
+	  //f1 = _fdopen(fd1, "w");
 	  /* We don't care about these pipes anymore,
 	     so close them. */
 	  CloseHandle(hChildStdoutRdDup);
 	  CloseHandle(hChildStderrRdDup);
+          PERROR("CloseHandle");
 	  break;
 
 	case _O_RDONLY | _O_TEXT:
 	  /* Case for reading from child Stdout in text mode. */
-	  fd1 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode);
-	  f1 = _fdopen(fd1, "r");
+	  fd1 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
+	  //f1 = _fdopen(fd1, "r");
 	  /* We don't care about these pipes anymore,
 	     so close them. */
 	  CloseHandle(hChildStdinWrDup);
 	  CloseHandle(hChildStderrRdDup);
+          PERROR("CloseHandle");
 	  break;
 
 	case _O_RDONLY | _O_BINARY:
 	  /* Case for readinig from child Stdout in
 	     binary mode. */
-	  fd1 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode);
-	  f1 = _fdopen(fd1, "rb");
+	  fd1 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
+	  //f1 = _fdopen(fd1, "rb");
 	  /* We don't care about these pipes anymore,
 	     so close them. */
 	  CloseHandle(hChildStdinWrDup);
 	  CloseHandle(hChildStderrRdDup);
+          PERROR("CloseHandle");
 	  break;
 
 	case _O_WRONLY | _O_BINARY:
 	  /* Case for writing to child Stdin in binary mode. */
-	  fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode);
-	  f1 = _fdopen(fd1, "wb");
+	  fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
+	  //f1 = _fdopen(fd1, "wb");
 	  /* We don't care about these pipes anymore,
 	     so close them. */
 	  CloseHandle(hChildStdoutRdDup);
 	  CloseHandle(hChildStderrRdDup);
+          PERROR("CloseHandle");
 	  break;
 	}
       file_count = 1;
@@ -331,13 +389,17 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
 	  m2 = "wb";
 	  }
 
-	fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode);
-	f1 = _fdopen(fd1, m2);
-	fd2 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode);
-	f2 = _fdopen(fd2, m1);
+	fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
+	//f1 = _fdopen(fd1, m2);
+	fd2 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
+	//f2 = _fdopen(fd2, m1);
+        PERROR("_open_osfhandle");
 
 	if (n != 4)
+          {
 	  CloseHandle(hChildStderrRdDup);
+          PERROR("CloseHandle");              
+          }
 
 	file_count = 2;
 	break;
@@ -359,12 +421,14 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
 	  m2 = "wb";
 	  }
 
-	fd1 = _open_osfhandle((intptr_t)hChildStdinWrDup, mode);
-	f1 = _fdopen(fd1, m2);
-	fd2 = _open_osfhandle((intptr_t)hChildStdoutRdDup, mode);
-	f2 = _fdopen(fd2, m1);
-	fd3 = _open_osfhandle((intptr_t)hChildStderrRdDup, mode);
-	f3 = _fdopen(fd3, m1);	
+
+	fd1 = _open_osfhandle(TO_INTPTR(hChildStdinWrDup), mode);
+	//f1 = _fdopen(fd1, m2);
+	fd2 = _open_osfhandle(TO_INTPTR(hChildStdoutRdDup), mode);
+	//f2 = _fdopen(fd2, m1);
+	fd3 = _open_osfhandle(TO_INTPTR(hChildStderrRdDup), mode);
+	//f3 = _fdopen(fd3, m1);	
+        PERROR("_open_osfhandle");
 
 	file_count = 3;
 	break;
@@ -414,29 +478,34 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
 
   if (!CloseHandle(hChildStdinRd))
     return win32_error("CloseHandle", NULL);
+  PERROR("CloseHandle");
 	  
   if (!CloseHandle(hChildStdoutWr))
     return win32_error("CloseHandle", NULL);
+  PERROR("CloseHandle");
 	  
   if ((n != 4) && (!CloseHandle(hChildStderrWr)))
     return win32_error("CloseHandle", NULL);
+  PERROR("CloseHandle");
   
   this->m_ProcessHandle = hProcess;
-  if ( f1 )
+  if ( fd1 >= 0 )
     {
-    this->m_StdIn = f1;
+    //  this->m_StdIn = f1;
     this->m_pStdIn = fd1;
     }
-  if ( f2 )
+  if ( fd2 >= 0 )
     {
-    this->m_StdOut = f2;
+    //  this->m_StdOut = f2;
     this->m_pStdOut = fd2;
     }
-  if ( f3 )
+  if ( fd3 >= 0 )
     {
-    this->m_StdErr = f3;
+    //  this->m_StdErr = f3;
     this->m_pStdErr = fd3;
     }
+  //std::cout << "Process created for real..." << std::endl;
+  //std::cout << fd1 << " " << fd2 << " " << fd3 << std::endl;
 
   return true;
 }
@@ -502,6 +571,7 @@ bool cmWin32ProcessExecution::PrivateClose(int timeout)
       }
     if (fserr.st_size > 0)
       {
+      //std::cout << "Some error" << std::endl;
       int dist = fserr.st_size;
       char buffer[1023];
       int len = read(this->m_pStdErr, buffer, 1023);
@@ -514,6 +584,7 @@ bool cmWin32ProcessExecution::PrivateClose(int timeout)
       }
     if (fsout.st_size > 0)
       {
+      //std::cout << "Some output" << std::endl;
       int dist = fsout.st_size;
       char buffer[1023];
       int len = read(this->m_pStdOut, buffer, 1023);
@@ -528,9 +599,13 @@ bool cmWin32ProcessExecution::PrivateClose(int timeout)
     GetExitCodeProcess(hProcess,&exitCode);
     if (exitCode != STILL_ACTIVE)
       {
+      //std::cout << "STILL_ACTIVE = " << STILL_ACTIVE << std::endl;
+      //std::cout << "Process is not active any more: " << exitCode << std::endl;
       break;
       }
     }  
+
+  //std::cout << "Waiting for process to close" << std::endl;
   
   if (WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED &&
       GetExitCodeProcess(hProcess, &exit_code)) 
@@ -554,6 +629,8 @@ bool cmWin32ProcessExecution::PrivateClose(int timeout)
       }
     result = -1;
     }
+
+  //std::cout << "Process closed with error code: " << result << std::endl;
 	
   /* Free up the native handle at this point */
   CloseHandle(hProcess);

+ 49 - 9
Source/cmWin32ProcessExecution.h

@@ -27,7 +27,6 @@
 
 #include "cmStandardIncludes.h"
 #include "windows.h"
-#include "stdio.h"
 
 class cmMakefile;
 
@@ -45,21 +44,59 @@ public:
     this->SetConsoleSpawn("w9xpopen.exe");
     this->Initialize();
     }
+
+  /**
+   * Initialize the process execution datastructure. Do not call while
+   * running the process.
+   */
   void Initialize() 
     {
     this->m_ProcessHandle = 0;
     this->m_ExitValue    = -1;
-    this->m_StdIn  =  0;
-    this->m_StdOut =  0;
-    this->m_StdErr =  0;
+    // Comment this out. Maybe we will need it in the future.
+    // file IO access to the process might be cool.
+    //this->m_StdIn  =  0;
+    //this->m_StdOut =  0;
+    //this->m_StdErr =  0;
+    this->m_pStdIn  =  -1;
+    this->m_pStdOut =  -1;
+    this->m_pStdErr =  -1;
     }
+  
+  /**
+   * Start the process in the directory path. Make sure that the
+   * executable is either in the path or specify the full path. The
+   * argument verbose specifies wether or not to display output while
+   * it is being generated.
+   */
   bool StartProcess(const char*, const char* path, bool verbose);
+
+  /**
+   * Wait for the process to finish. If timeout is specified, it will
+   * break the process after timeout expires. (Timeout code is not yet
+   * implemented.
+   */
   bool Wait(int timeout);
+
+  /**
+   * Get the output of the process (mixed stdout and stderr) as
+   * std::string.
+   */
   const std::string GetOutput() const { return this->m_Output; }
+
+  /**
+   * Get the return value of the process. If the process is still
+   * running, the return value is -1.
+   */
   int GetExitValue() const { return this->m_ExitValue; }
 
+  /**
+   * On Windows 9x there is a bug in the process execution code which
+   * may result in blocking. That is why this workaround is
+   * used. Specify the console spawn, which should run the
+   * Windows9xHack code.
+   */
   void SetConsoleSpawn(const char* prog) { this->m_ConsoleSpawn = prog; }
-
   static int Windows9xHack(const char* command);
 
 private:
@@ -67,10 +104,13 @@ private:
   bool PrivateClose(int timeout);
 
   HANDLE m_ProcessHandle;
-  FILE* m_StdIn;
-  FILE* m_StdOut;
-  FILE* m_StdErr;
-  
+
+  // Comment this out. Maybe we will need it in the future.
+  // file IO access to the process might be cool.
+  // FILE* m_StdIn;
+  // FILE* m_StdOut;
+  // FILE* m_StdErr;
+
   int m_pStdIn;
   int m_pStdOut;
   int m_pStdErr;