[Python-checkins] CVS: python/dist/src/Modules posixmodule.c,2.159,2.160

Fredrik Lundh python-dev@python.org
2000年7月23日 12:47:15 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory slayer.i.sourceforge.net:/tmp/cvs-serv9617/Modules
Modified Files:
	posixmodule.c 
Log Message:
-- added code to the new Windows popen functions to make close
 return the exit code. Only works on Windows NT/2000, due to
 limitations in the Win9X shell.
 (based on patch #100941 by David Bolen)
Index: posixmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v
retrieving revision 2.159
retrieving revision 2.160
diff -C2 -r2.159 -r2.160
*** posixmodule.c	2000年07月22日 23:57:55	2.159
--- posixmodule.c	2000年07月23日 19:47:12	2.160
***************
*** 2118,2121 ****
--- 2118,2122 ----
 * Written by Bill Tutt <billtut@microsoft.com>. Minor tweaks
 * and 2.0 integration by Fredrik Lundh <fredrik@pythonware.com>
+ * Return code handling by David Bolen.
 */
 
***************
*** 2131,2135 ****
--- 2132,2145 ----
 
 static PyObject *_PyPopen(char *, int, int);
+ static int _PyPclose(FILE *file);
 
+ /*
+ * Internal dictionary mapping popen* file pointers to process handles,
+ * in order to maintain a link to the process handle until the file is
+ * closed, at which point the process exit code is returned to the caller.
+ */
+ static PyObject *_PyPopenProcs = NULL;
+ 
+ 
 /* popen that works from a GUI.
 *
***************
*** 2286,2290 ****
 
 static int
! _PyPopenCreateProcess(char *cmdstring,
 		 HANDLE hStdin,
 		 HANDLE hStdout,
--- 2296,2300 ----
 
 static int
! _PyPopenCreateProcess(char *cmdstring, FILE *file,
 		 HANDLE hStdin,
 		 HANDLE hStdout,
***************
*** 2362,2367 ****
 			 &piProcInfo) ) {
 		/* Close the handles now so anyone waiting is woken. */
- 		CloseHandle(piProcInfo.hProcess);
 		CloseHandle(piProcInfo.hThread);
 		return TRUE;
 	}
--- 2372,2397 ----
 			 &piProcInfo) ) {
 		/* Close the handles now so anyone waiting is woken. */
 		CloseHandle(piProcInfo.hThread);
+ 
+ 		/*
+ 		 * Try to insert our process handle into the internal
+ 		 * dictionary so we can find it later when trying 
+ 		 * to close this file.
+ 		 */
+ 		if (!_PyPopenProcs)
+ 			_PyPopenProcs = PyDict_New();
+ 		if (_PyPopenProcs) {
+ 			PyObject *hProcessObj, *fileObj;
+ 
+ 			hProcessObj = PyLong_FromVoidPtr(piProcInfo.hProcess);
+ 			fileObj = PyLong_FromVoidPtr(file);
+ 
+ 			if (!hProcessObj || !fileObj ||
+ 				PyDict_SetItem(_PyPopenProcs,
+ 							 fileObj, hProcessObj) < 0) {
+ 				/* Insert failure - close handle to prevent leak */
+ 				CloseHandle(piProcInfo.hProcess);
+ 			}
+ 		}
 		return TRUE;
 	}
***************
*** 2440,2444 ****
 			 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
 			 f1 = _fdopen(fd1, "w");
! 			 f = PyFile_FromFile(f1, cmdstring, "w", fclose);
 			 PyFile_SetBufSize(f, 0);
 			 /* We don't care about these pipes anymore, so close them. */
--- 2470,2474 ----
 			 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
 			 f1 = _fdopen(fd1, "w");
! 			 f = PyFile_FromFile(f1, cmdstring, "w", _PyPclose);
 			 PyFile_SetBufSize(f, 0);
 			 /* We don't care about these pipes anymore, so close them. */
***************
*** 2451,2455 ****
 			 fd1 = _open_osfhandle((long)hChildStdoutRdDup, mode);
 			 f1 = _fdopen(fd1, "r");
! 			 f = PyFile_FromFile(f1, cmdstring, "r", fclose);
 			 PyFile_SetBufSize(f, 0);
 			 /* We don't care about these pipes anymore, so close them. */
--- 2481,2485 ----
 			 fd1 = _open_osfhandle((long)hChildStdoutRdDup, mode);
 			 f1 = _fdopen(fd1, "r");
! 			 f = PyFile_FromFile(f1, cmdstring, "r", _PyPclose);
 			 PyFile_SetBufSize(f, 0);
 			 /* We don't care about these pipes anymore, so close them. */
***************
*** 2462,2466 ****
 			 fd1 = _open_osfhandle((long)hChildStdoutRdDup, mode);
 			 f1 = _fdopen(fd1, "rb");
! 			 f = PyFile_FromFile(f1, cmdstring, "rb", fclose);
 			 PyFile_SetBufSize(f, 0);
 			 /* We don't care about these pipes anymore, so close them. */
--- 2492,2496 ----
 			 fd1 = _open_osfhandle((long)hChildStdoutRdDup, mode);
 			 f1 = _fdopen(fd1, "rb");
! 			 f = PyFile_FromFile(f1, cmdstring, "rb", _PyPclose);
 			 PyFile_SetBufSize(f, 0);
 			 /* We don't care about these pipes anymore, so close them. */
***************
*** 2473,2477 ****
 			 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
 			 f1 = _fdopen(fd1, "wb");
! 			 f = PyFile_FromFile(f1, cmdstring, "wb", fclose);
 			 PyFile_SetBufSize(f, 0);
 			 /* We don't care about these pipes anymore, so close them. */
--- 2503,2507 ----
 			 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
 			 f1 = _fdopen(fd1, "wb");
! 			 f = PyFile_FromFile(f1, cmdstring, "wb", _PyPclose);
 			 PyFile_SetBufSize(f, 0);
 			 /* We don't care about these pipes anymore, so close them. */
***************
*** 2500,2504 ****
 		 fd2 = _open_osfhandle((long)hChildStdoutRdDup, mode);
 		 f2 = _fdopen(fd2, m1);
! 		 p1 = PyFile_FromFile(f1, cmdstring, m2, fclose);
 		 PyFile_SetBufSize(p1, 0);
 		 p2 = PyFile_FromFile(f2, cmdstring, m1, fclose);
--- 2530,2534 ----
 		 fd2 = _open_osfhandle((long)hChildStdoutRdDup, mode);
 		 f2 = _fdopen(fd2, m1);
! 		 p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
 		 PyFile_SetBufSize(p1, 0);
 		 p2 = PyFile_FromFile(f2, cmdstring, m1, fclose);
***************
*** 2531,2535 ****
 		 fd3 = _open_osfhandle((long)hChildStderrRdDup, mode);
 		 f3 = _fdopen(fd3, m1);
! 		 p1 = PyFile_FromFile(f1, cmdstring, m2, fclose);
 		 p2 = PyFile_FromFile(f2, cmdstring, m1, fclose);
 		 p3 = PyFile_FromFile(f3, cmdstring, m1, fclose);
--- 2561,2565 ----
 		 fd3 = _open_osfhandle((long)hChildStderrRdDup, mode);
 		 f3 = _fdopen(fd3, m1);
! 		 p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
 		 p2 = PyFile_FromFile(f2, cmdstring, m1, fclose);
 		 p3 = PyFile_FromFile(f3, cmdstring, m1, fclose);
***************
*** 2544,2547 ****
--- 2574,2578 ----
 	 if (n == POPEN_4) {
 		 if (!_PyPopenCreateProcess(cmdstring,
+ 					 f1,
 					 hChildStdinRd,
 					 hChildStdoutWr,
***************
*** 2551,2554 ****
--- 2582,2586 ----
 	 else {
 		 if (!_PyPopenCreateProcess(cmdstring,
+ 					 f1,
 					 hChildStdinRd,
 					 hChildStdoutWr,
***************
*** 2573,2576 ****
--- 2605,2658 ----
 
 	 return f;
+ }
+ 
+ /*
+ * Wrapper for fclose() to use for popen* files, so we can retrieve the
+ * exit code for the child process and return as a result of the close.
+ */
+ static int _PyPclose(FILE *file)
+ {
+ 	int result = 0;
+ 	DWORD exit_code;
+ 	HANDLE hProcess;
+ 	PyObject *hProcessObj, *fileObj;
+ 
+ 	if (_PyPopenProcs) {
+ 		fileObj = PyLong_FromVoidPtr(file);
+ 		if (fileObj) {
+ 			hProcessObj = PyDict_GetItem(_PyPopenProcs, fileObj);
+ 			if (hProcessObj) {
+ 				hProcess = PyLong_AsVoidPtr(hProcessObj);
+ 				if (GetExitCodeProcess(hProcess, &exit_code)) {
+ 					/* Possible truncation here in 16-bit environments, but
+ 					 * real exit codes are just the lower byte in any event.
+ 					 */
+ 					result = exit_code;
+ 					if (result == STILL_ACTIVE)
+ 						result = 0; /* Minimize confusion */
+ 				} else {
+ 					/* No good way to bubble up an error, so instead we just
+ 					 * return the Windows last error shifted above standard
+ 					 * exit codes.	This will truncate in 16-bits but should
+ 					 * be fine in 32 and at least distinguishes the problem.
+ 					 */
+ 					result = (GetLastError() << 8);
+ 				}
+ 
+ 				/* Free up the native handle at this point */
+ 				CloseHandle(hProcess);
+ 
+ 				/* Remove from dictionary and flush dictionary if empty */
+ 				PyDict_DelItem(_PyPopenProcs, fileObj);
+ 				if (PyDict_Size(_PyPopenProcs) == 0) {
+ 					Py_DECREF(_PyPopenProcs);
+ 					_PyPopenProcs = NULL;
+ 				}
+ 			} /* if hProcessObj */
+ 		} /* if fileObj */
+ 	} /* if _PyPopenProcs */
+ 
+ 	fclose(file);
+ 	return result;
 }
 #else

AltStyle によって変換されたページ (->オリジナル) /