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

ambv webhook-mailer at python.org
Wed Nov 17 15:12:27 EST 2021


https://github.com/python/cpython/commit/b919d8105c4d77f00509b6d3ab2073f09db640de
commit: b919d8105c4d77f00509b6d3ab2073f09db640de
branch: main
author: Victor Stinner <vstinner at python.org>
committer: ambv <lukasz at langa.pl>
date: 2021-11-17T21:12:20+01:00
summary:

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

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

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 67f995a759980..8aef3d810d316 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -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, "...");
     }



More information about the Python-checkins mailing list