summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstephanelsmith <stephane.smith@titansensor.com>2023-07-26 02:52:56 +0000
committerDamien George <damien@micropython.org>2023-09-01 17:39:38 +1000
commit1c047742a273382241e8cfddb12a1d8b4f7f59ab (patch)
tree9736ebbc0ca3b52a10c889d3d37562c87be297ec
parent633599cdd500d3a2c99193f2c4340ac823d1a8a8 (diff)
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 <module> OSError: 45 On unix: py3 b'hello world\n' upy b'hello world\n' Signed-off-by: stephanelsmith <stephane.smith@titansensor.com>
-rw-r--r--extmod/vfs_posix_file.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c
index d70bc4738..cce7a79af 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;