From 1c047742a273382241e8cfddb12a1d8b4f7f59ab Mon Sep 17 00:00:00 2001 From: stephanelsmith Date: Wed, 26 Jul 2023 02:52:56 +0000 Subject: [PATCH] extmod/vfs_posix_file: Fix flush handling on macOS. On macOS, if running micropython from subprocess.check_output, then a stdout.flush() raises error 45. Here's a test case. This will run fine on linux, but crashes on macOS with error 45. import sys import subprocess import tempfile with tempfile.NamedTemporaryFile('w') as fp: fp.write(''' import sys sys.stdout.write('hello world') sys.stdout.flush() print('') ''') fp.flush() print('py3') o = subprocess.check_output(f'python3 {fp.name}'.split()) print(o) print('upy') o = subprocess.check_output(f'micropython {fp.name}'.split()) print(o) On macOS: py3 b'hello world\n' upy Traceback (most recent call last): File "...", line 4, in OSError: 45 On unix: py3 b'hello world\n' upy b'hello world\n' Signed-off-by: stephanelsmith --- extmod/vfs_posix_file.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index d70bc4738e..cce7a79af7 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -153,12 +153,17 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ switch (request) { case MP_STREAM_FLUSH: { int ret; + // fsync(stdin/stdout/stderr) may fail with EINVAL (or ENOTSUP on macos), + // but don't propagate that error out. Because data is not buffered by + // us, and stdin/out/err.flush() should just be a no-op. + #ifdef __APPLE__ + #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == ENOTSUP) + #else + #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL) + #endif MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), { - if (err == EINVAL + if (VFS_POSIX_STREAM_STDIO_ERR_CATCH && (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) { - // fsync(stdin/stdout/stderr) may fail with EINVAL, but don't propagate that - // error out. Because data is not buffered by us, and stdin/out/err.flush() - // should just be a no-op. return 0; } *errcode = err;