diff options
author | Christian Heimes <christian@python.org> | 2022-03-22 16:08:51 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-22 16:08:51 (GMT) |
commit | 9b889b5bda32c2610f98114d94750ba5f3260b58 (patch) | |
tree | 59cd31b9b763ce85b96b06cef2b8c1fadf5406d9 /Parser/tokenizer.c | |
parent | e03db6d5be7cf2e6b7b55284985c404de98a9420 (diff) | |
download | cpython-9b889b5bda32c2610f98114d94750ba5f3260b58.zip cpython-9b889b5bda32c2610f98114d94750ba5f3260b58.tar.gz cpython-9b889b5bda32c2610f98114d94750ba5f3260b58.tar.bz2 |
bpo-46315: Use fopencookie() to avoid dup() in _PyTokenizer_FindEncodingFilename (GH-32033)
WASI does not have dup() and Emscripten's emulation is slow.
Diffstat (limited to 'Parser/tokenizer.c')
-rw-r--r-- | Parser/tokenizer.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 90dc8a2..0941bca 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -2072,6 +2072,39 @@ _PyTokenizer_Get(struct tok_state *tok, return result; } +#if defined(__wasi__) || defined(__EMSCRIPTEN__) +// fdopen() with borrowed fd. WASI does not provide dup() and Emscripten's +// dup() emulation with open() is slow. +typedef union { + void *cookie; + int fd; +} borrowed; + +static ssize_t +borrow_read(void *cookie, char *buf, size_t size) +{ + borrowed b = {.cookie = cookie}; + return read(b.fd, (void *)buf, size); +} + +static FILE * +fdopen_borrow(int fd) { + // supports only reading. seek fails. close and write are no-ops. + cookie_io_functions_t io_cb = {borrow_read, NULL, NULL, NULL}; + borrowed b = {.fd = fd}; + return fopencookie(b.cookie, "r", io_cb); +} +#else +static FILE * +fdopen_borrow(int fd) { + fd = _Py_dup(fd); + if (fd < 0) { + return NULL; + } + return fdopen(fd, "r"); +} +#endif + /* Get the encoding of a Python file. Check for the coding cookie and check if the file starts with a BOM. @@ -2091,12 +2124,7 @@ _PyTokenizer_FindEncodingFilename(int fd, PyObject *filename) const char *p_end = NULL; char *encoding = NULL; - fd = _Py_dup(fd); - if (fd < 0) { - return NULL; - } - - fp = fdopen(fd, "r"); + fp = fdopen_borrow(fd); if (fp == NULL) { return NULL; } |