]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596)
authorVictor Stinner <vstinner@python.org>
Wed, 17 Nov 2021 20:12:20 +0000 (21:12 +0100)
committerGitHub <noreply@github.com>
Wed, 17 Nov 2021 20:12:20 +0000 (21:12 +0100)
If the string is ASCII only and doesn't need to escape characters,
write the whole string with a single write() syscall.

Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst [new file with mode: 0644]
Python/traceback.c

diff --git a/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst b/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst
new file mode 100644 (file)
index 0000000..049449f
--- /dev/null
@@ -0,0 +1,5 @@
+:mod:`faulthandler` can now write ASCII-only strings (like filenames and
+function names) with a single write() syscall when dumping a traceback. It
+reduces the risk of getting an unreadable dump when two threads or two
+processes dump a traceback to the same file (like stderr) at the same time.
+Patch by Victor Stinner.
index 67f995a7599802e6129af6ffe2e944b55a0db13c..8aef3d810d316281a4a09b49f05680225ae46c23 100644 (file)
@@ -1072,6 +1072,26 @@ _Py_DumpASCII(int fd, PyObject *text)
         truncated = 0;
     }
 
+    // Is an ASCII string?
+    if (ascii->state.ascii) {
+        assert(kind == PyUnicode_1BYTE_KIND);
+        char *str = data;
+
+        int need_escape = 0;
+        for (i=0; i < size; i++) {
+            ch = str[i];
+            if (!(' ' <= ch && ch <= 126)) {
+                need_escape = 1;
+                break;
+            }
+        }
+        if (!need_escape) {
+            // The string can be written with a single write() syscall
+            _Py_write_noraise(fd, str, size);
+            goto done;
+        }
+    }
+
     for (i=0; i < size; i++) {
         if (kind != PyUnicode_WCHAR_KIND)
             ch = PyUnicode_READ(kind, data, i);
@@ -1095,6 +1115,8 @@ _Py_DumpASCII(int fd, PyObject *text)
             _Py_DumpHexadecimal(fd, ch, 8);
         }
     }
+
+done:
     if (truncated) {
         PUTS(fd, "...");
     }