Issue #25182: The stdprinter (used as sys.stderr before the io module is
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 30 Sep 2015 12:46:53 +0000 (15:46 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Wed, 30 Sep 2015 12:46:53 +0000 (15:46 +0300)
imported at startup) now uses the backslashreplace error handler.

Misc/NEWS
Objects/fileobject.c

index 3d5dfa94db0114d73219e0ac8a8c753d9947d87b..c3068c4260b5287fd02945ece95f4e622a1e37b2 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: tba
 Core and Builtins
 -----------------
 
+- Issue #25182: The stdprinter (used as sys.stderr before the io module is
+  imported at startup) now uses the backslashreplace error handler.
+
 - Issue #24891: Fix a race condition at Python startup if the file descriptor
   of stdin (0), stdout (1) or stderr (2) is closed while Python is creating
   sys.stdin, sys.stdout and sys.stderr objects. These attributes are now set
index 596f909755d7487676cdbda77c2c6ece7026e9c0..403d718dfe5489894c5dad08e3091c113265c195 100644 (file)
@@ -372,8 +372,11 @@ PyFile_NewStdPrinter(int fd)
 static PyObject *
 stdprinter_write(PyStdPrinter_Object *self, PyObject *args)
 {
-    char *c;
+    PyObject *unicode;
+    PyObject *bytes = NULL;
+    char *str;
     Py_ssize_t n;
+    int _errno;
 
     if (self->fd < 0) {
         /* fd might be invalid on Windows
@@ -383,24 +386,37 @@ stdprinter_write(PyStdPrinter_Object *self, PyObject *args)
         Py_RETURN_NONE;
     }
 
-    if (!PyArg_ParseTuple(args, "s", &c)) {
+    if (!PyArg_ParseTuple(args, "U", &unicode))
         return NULL;
+
+    /* encode Unicode to UTF-8 */
+    str = PyUnicode_AsUTF8AndSize(unicode, &n);
+    if (str == NULL) {
+        PyErr_Clear();
+        bytes = _PyUnicode_AsUTF8String(unicode, "backslashreplace");
+        if (bytes == NULL)
+            return NULL;
+        if (PyBytes_AsStringAndSize(bytes, &str, &n) < 0) {
+            Py_DECREF(bytes);
+            return NULL;
+        }
     }
-    n = strlen(c);
 
     Py_BEGIN_ALLOW_THREADS
     errno = 0;
 #ifdef MS_WINDOWS
     if (n > INT_MAX)
         n = INT_MAX;
-    n = write(self->fd, c, (int)n);
+    n = write(self->fd, str, (int)n);
 #else
-    n = write(self->fd, c, n);
+    n = write(self->fd, str, n);
 #endif
+    _errno = errno;
     Py_END_ALLOW_THREADS
+    Py_XDECREF(bytes);
 
     if (n < 0) {
-        if (errno == EAGAIN)
+        if (_errno == EAGAIN)
             Py_RETURN_NONE;
         PyErr_SetFromErrno(PyExc_IOError);
         return NULL;