Browse Source

extmod/vfs_posix_file: Skip flush of tty handles in msvc debug builds.

In MSVC debug builds with debug error reporting set to showing a dialog (to
allow attaching the debugger), any application which imports the logging
module and leaves the default handlers would result in this dialog because
logging.shutdown is called at exit and that flushes the default handler
which has stderr as its stream.

This commit fixes that by not fsync'ing stdin/out/err.

Also adds a comment related to checking whether a file is stdin/out/err,
which is difficult to fix properly.

Signed-off-by: stijn <stijn@ignitron.net>
pull/12652/head
stijn 1 year ago
committed by Damien George
parent
commit
6835743dcc
  1. 15
      extmod/vfs_posix_file.c

15
extmod/vfs_posix_file.c

@ -160,12 +160,27 @@ static mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_
#if defined(__APPLE__)
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == ENOTSUP)
#elif defined(_MSC_VER)
// In debug builds fsync (i.e. _commit on windows) will generate a debug report via _ASSERTE when
// called with non-redirected stdin/stdout/stderr (i.e. _isatty) handles because FlushFileBuffers,
// which it calls internally, will fail since console output is not buffered.
// In release builds it also fails, but merely returns an error which is handled appropriately below.
// The check for the handle being stdin/stdout/stderr is added explicitly because according to
// the documentation _isatty is also true for serial ports for instance.
#ifdef _DEBUG
if ((o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO) && _isatty(o->fd)) {
return 0;
}
#endif
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == EBADF)
#else
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL)
#endif
MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), {
if (VFS_POSIX_STREAM_STDIO_ERR_CATCH
// Note: comparing fd against the standard FILENOs is technically not correct, for example:
// sys.stderr.close() in Python code results in close(STDERR_FILENO) here, but because
// open() uses the next available file descriptor, opening an arbitrary file with
// fd = open('/some/file') means that fd becomes STDERR_FILENO.
&& (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) {
return 0;
}

Loading…
Cancel
Save