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

Fixes #947
This commit is contained in:
rdb 2020-09-12 15:03:56 +02:00
parent a94914fd86
commit e443acd7a0

View File

@ -28,6 +28,8 @@
# if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 5
# define Py_DecodeLocale _Py_char2wchar
# endif
# include "structmember.h"
#endif
/* 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
}
/**
* 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 */
#ifdef WIN_UNICODE
@ -483,6 +530,24 @@ int Py_FrozenMain(int argc, char **argv)
}
#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)
fprintf(stderr, "Python %s\n%s\n",
Py_GetVersion(), Py_GetCopyright());