From 7ed84a6590589b403cf283b47db9ce2bd79d26c0 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 15 Apr 2018 19:05:06 +0200 Subject: [PATCH] workaround for bug in VS 2013 that occurs at Python init time --- src/Base/Interpreter.cpp | 7 +++++++ src/Gui/Application.cpp | 2 +- src/Main/MainGui.cpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/Base/Interpreter.cpp b/src/Base/Interpreter.cpp index dfc0ae4905..b3fad42e94 100644 --- a/src/Base/Interpreter.cpp +++ b/src/Base/Interpreter.cpp @@ -485,6 +485,12 @@ const char* InterpreterSingleton::init(int argc,char *argv[]) #else Py_SetProgramName(argv[0]); #endif + // There is a serious bug in VS from 2010 until 2013 where the file descriptor for stdin, stdout or stderr + // returns a valid value for GUI applications (i.e. subsytem = Windows) where it shouldn't. + // This causes Python to fail during initialization. + // A workaround is to use freopen on stdin, stdout and stderr. See the class Redirection inside main() + // https://bugs.python.org/issue17797#msg197474 + // Py_Initialize(); PyEval_InitThreads(); #if PY_MAJOR_VERSION >= 3 @@ -505,6 +511,7 @@ const char* InterpreterSingleton::init(int argc,char *argv[]) this->_global = PyEval_SaveThread(); } #if PY_MAJOR_VERSION >= 3 + PyGILStateLocker lock; #if PY_MINOR_VERSION >= 5 return Py_EncodeLocale(Py_GetPath(),NULL); #else diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 1d968071ab..820dc8c5d2 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -1032,6 +1032,7 @@ bool Application::activateWorkbench(const char* name) if (oldWb && oldWb->name() == name) return false; // already active + Base::PyGILStateLocker lock; // we check for the currently active workbench and call its 'Deactivated' // method, if available PyObject* pcOldWorkbench = 0; @@ -1040,7 +1041,6 @@ bool Application::activateWorkbench(const char* name) } // get the python workbench object from the dictionary - Base::PyGILStateLocker lock; PyObject* pcWorkbench = 0; pcWorkbench = PyDict_GetItemString(_pcWorkbenchDictionary, name); // test if the workbench exists diff --git a/src/Main/MainGui.cpp b/src/Main/MainGui.cpp index 8c86ed43c8..5d0557e115 100644 --- a/src/Main/MainGui.cpp +++ b/src/Main/MainGui.cpp @@ -71,6 +71,29 @@ const char sBanner[] = "\xc2\xa9 Juergen Riegel, Werner Mayer, Yorik van Havre 2 void InitMiniDumpWriter(const std::string&); #endif +class Redirection +{ +public: + Redirection(FILE* f) + : fi(Base::FileInfo::getTempFileName()), file(f) + { +#ifdef WIN32 + _wfreopen(fi.toStdWString().c_str(),L"w",file); +#else + freopen(fi.filePath().c_str(),"w",file); +#endif + } + ~Redirection() + { + fclose(file); + fi.deleteFile(); + } + +private: + Base::FileInfo fi; + FILE* file; +}; + #if defined (FC_OS_LINUX) || defined(FC_OS_BSD) QString myDecoderFunc(const QByteArray &localFileName) { @@ -133,6 +156,13 @@ int main( int argc, char ** argv ) } #endif +#if PY_MAJOR_VERSION >= 3 +#if defined(_MSC_VER) && _MSC_VER <= 1800 + // See InterpreterSingleton::init + Redirection out(stdout), err(stderr), inp(stdin); +#endif +#endif // PY_MAJOR_VERSION + // Name and Version of the Application App::Application::Config()["ExeName"] = "FreeCAD"; App::Application::Config()["ExeVendor"] = "FreeCAD";