Skip to content

Commit 4ffde90

Browse files
bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596) (GH-29598)
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 b919d81) Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent 1079b3e commit 4ffde90

2 files changed

Lines changed: 27 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
:mod:`faulthandler` can now write ASCII-only strings (like filenames and
2+
function names) with a single write() syscall when dumping a traceback. It
3+
reduces the risk of getting an unreadable dump when two threads or two
4+
processes dump a traceback to the same file (like stderr) at the same time.
5+
Patch by Victor Stinner.

Python/traceback.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,26 @@ _Py_DumpASCII(int fd, PyObject *text)
717717
truncated = 0;
718718
}
719719

720+
// Is an ASCII string?
721+
if (ascii->state.ascii) {
722+
assert(kind == PyUnicode_1BYTE_KIND);
723+
char *str = data;
724+
725+
int need_escape = 0;
726+
for (i=0; i < size; i++) {
727+
ch = str[i];
728+
if (!(' ' <= ch && ch <= 126)) {
729+
need_escape = 1;
730+
break;
731+
}
732+
}
733+
if (!need_escape) {
734+
// The string can be written with a single write() syscall
735+
_Py_write_noraise(fd, str, size);
736+
goto done;
737+
}
738+
}
739+
720740
for (i=0; i < size; i++) {
721741
if (kind != PyUnicode_WCHAR_KIND)
722742
ch = PyUnicode_READ(kind, data, i);
@@ -740,6 +760,8 @@ _Py_DumpASCII(int fd, PyObject *text)
740760
_Py_DumpHexadecimal(fd, ch, 8);
741761
}
742762
}
763+
764+
done:
743765
if (truncated) {
744766
PUTS(fd, "...");
745767
}

0 commit comments

Comments
 (0)