[Python-checkins] bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596) (GH-29597)

ambv webhook-mailer at python.org
Wed Nov 17 17:00:03 EST 2021


https://github.com/python/cpython/commit/ac89f8cab79800195687dd141de472f90c626ec3
commit: ac89f8cab79800195687dd141de472f90c626ec3
branch: 3.9
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: ambv <lukasz at langa.pl>
date: 2021-11-17T22:59:42+01:00
summary:

bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596) (GH-29597)

If the string is ASCII only and doesn't need to escape characters,
write the whole string with a single write() syscall.
(cherry picked from commit b919d8105c4d77f00509b6d3ab2073f09db640de)

Co-authored-by: Victor Stinner <vstinner at python.org>

files:
A Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst
M 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
index 0000000000000..049449ff0a4a1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst
@@ -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.
diff --git a/Python/traceback.c b/Python/traceback.c
index 83f3074f43d05..23d0e38e7377c 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -719,6 +719,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);
@@ -742,6 +762,8 @@ _Py_DumpASCII(int fd, PyObject *text)
             _Py_DumpHexadecimal(fd, ch, 8);
         }
     }
+
+done:
     if (truncated) {
         PUTS(fd, "...");
     }



More information about the Python-checkins mailing list