[Python-Dev] Fix to allow os.popen to work from pythonw.exe

Barry Scott barry@scottb.demon.co.uk
Thu, 6 Jul 2000 23:58:17 +0100


os.popen fails to work if pythonw.exe is used to start python. This is
true for 1.5.2 and 1.6a2.

The root cause of the problem is in the Microsoft C RTL implementation
of _popen(). _popen() will fail if there is not a valid file descriptor
for stdin or stdout.

The following replacement for WinMain.c works around the problem.
I also ensure a valid descriptor for stderr for completeness.

This was compiled and test under VC++ 6.0 SP3 on Windows 2000.

		BArry


-------------------------------- WinMain.c -------------------------
/* Minimal main program -- everything is loaded from the library. */

#include <windows.h>
#include "Python.h"
#include <fcntl.h>
#include <sys/stat.h>

extern int Py_Main();

int WINAPI WinMain(
    HINSTANCE hInstance,      // handle to current instance
    HINSTANCE hPrevInstance,  // handle to previous instance
    LPSTR lpCmdLine,          // pointer to command line
    int nCmdShow              // show state of window
)
{
	/*
	 * make sure that the C RTL has valid file descriptors for
	 * stdin, stdout, stderr. Use the NUL device.
	 * This allows popen to work under pythonw.
	 *
	 * When pythonw.exe starts the C RTL function _ioinit is called
	 * first. WinMain is called later hence the need to check for
	 * invalid handles.
	 *
	 * Note: FILE stdin, stdout, stderr do not use the file descriptors
	 * setup here. They are already initialised before WinMain was called.
	 */

	int null_file;
	null_file = open( "NUL", _O_RDWR );

	/* check for STDIN is invalid */
	if( _get_osfhandle( 0 ) == -1 )
		{ dup2( null_file, 0 );	}

	/* check for STDOUT is invalid */
	if( _get_osfhandle( 1 ) == -1 )
		{ dup2( null_file, 1 );	}

	/* check for STDERR is invalid */
	if( _get_osfhandle( 2 ) == -1 )
		{ dup2( null_file, 2 );	}

	close( null_file );

	return Py_Main(__argc, __argv);
}