Browse Source

deploy-stub: Enable line_buffering on Windows when writing to log file

Fixes #947
rdb 5 years ago
parent
commit
e443acd7a0
1 changed files with 65 additions and 0 deletions
  1. 65 0
      pandatool/src/deploy-stub/deploy-stub.c

+ 65 - 0
pandatool/src/deploy-stub/deploy-stub.c

@@ -28,6 +28,8 @@
 #  if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 5
 #  if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 5
 #    define Py_DecodeLocale _Py_char2wchar
 #    define Py_DecodeLocale _Py_char2wchar
 #  endif
 #  endif
+
+#  include "structmember.h"
 #endif
 #endif
 
 
 /* Leave room for future expansion.  We only read pointer 0, but there are
 /* Leave room for future expansion.  We only read pointer 0, but there are
@@ -343,6 +345,51 @@ static int setup_logging(const char *path, int append) {
 #endif
 #endif
 }
 }
 
 
+/**
+ * Sets the line_buffering property on a TextIOWrapper object.
+ */
+#if PY_MAJOR_VERSION >= 3
+static int enable_line_buffering(PyObject *file) {
+#if PY_VERSION_HEX >= 0x03070000
+  /* Python 3.7 has a useful reconfigure() method. */
+  PyObject *kwargs = _PyDict_NewPresized(1);
+  PyDict_SetItemString(kwargs, "line_buffering", Py_True);
+  PyObject *args = PyTuple_New(0);
+
+  PyObject *method = PyObject_GetAttrString(file, "reconfigure");
+  if (method != NULL) {
+    PyObject *result = PyObject_Call(method, args, kwargs);
+    Py_DECREF(method);
+    if (result != NULL) {
+      Py_DECREF(result);
+    } else {
+      PyErr_Clear();
+      return 0;
+    }
+  }
+  Py_DECREF(kwargs);
+  Py_DECREF(args);
+#else
+  /* Older versions just don't expose a way to reconfigure(), but it's still
+     safe to override the property; we just have to use a hack to do it,
+     because it's officially marked "readonly". */
+
+  PyTypeObject *type = Py_TYPE(file);
+  PyMemberDef *member = type->tp_members;
+
+  while (member != NULL && member->name != NULL) {
+    if (strcmp(member->name, "line_buffering") == 0) {
+      *((char *)file + member->offset) = 1;
+      return 1;
+    }
+    ++member;
+  }
+  fflush(stdout);
+#endif
+  return 1;
+}
+#endif
+
 /* Main program */
 /* Main program */
 
 
 #ifdef WIN_UNICODE
 #ifdef WIN_UNICODE
@@ -483,6 +530,24 @@ int Py_FrozenMain(int argc, char **argv)
     }
     }
 #endif
 #endif
 
 
+#if defined(MS_WINDOWS) && PY_VERSION_HEX >= 0x03040000
+    /* Ensure that line buffering is enabled on the output streams. */
+    if (!unbuffered) {
+      /* Python 3.7 has a useful reconfigure() method. */
+      PyObject *sys_stream;
+      sys_stream = PySys_GetObject("__stdout__");
+      if (sys_stream && !enable_line_buffering(sys_stream)) {
+        fprintf(stderr, "Failed to enable line buffering on sys.stdout\n");
+        fflush(stderr);
+      }
+      sys_stream = PySys_GetObject("__stderr__");
+      if (sys_stream && !enable_line_buffering(sys_stream)) {
+        fprintf(stderr, "Failed to enable line buffering on sys.stderr\n");
+        fflush(stderr);
+      }
+    }
+#endif
+
     if (Py_VerboseFlag)
     if (Py_VerboseFlag)
         fprintf(stderr, "Python %s\n%s\n",
         fprintf(stderr, "Python %s\n%s\n",
             Py_GetVersion(), Py_GetCopyright());
             Py_GetVersion(), Py_GetCopyright());