From 7cddb175761ea07bcaea121897fd2c6ce4404cc3 Mon Sep 17 00:00:00 2001 From: Balazs Racz Date: Wed, 7 Oct 2020 23:25:41 +0200 Subject: [PATCH] Adds an intermediate stage in closing an fd. Adds a new bit to mark an fd being in shutdown. This is a state during close that marks the fd as being bad, with all kernel calls (from other threads) returning EBADF if they refer to this fd. At the same time the fd is not marked as free for reuse by another open. This fixes the race condition in https://github.com/bakerstu/openmrn/issues/440 --- src/freertos_drivers/common/Device.cxx | 1 + src/freertos_drivers/common/Devtab.hxx | 1 + src/freertos_drivers/common/Fileio.cxx | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/freertos_drivers/common/Device.cxx b/src/freertos_drivers/common/Device.cxx index 5530fdab9..d6577e301 100644 --- a/src/freertos_drivers/common/Device.cxx +++ b/src/freertos_drivers/common/Device.cxx @@ -144,6 +144,7 @@ int Device::close(struct _reent *reent, int fd) // stdin, stdout, and stderr never get closed return 0; } + files[fd].inshdn = true; int result = f->dev->close(f); if (result < 0) { diff --git a/src/freertos_drivers/common/Devtab.hxx b/src/freertos_drivers/common/Devtab.hxx index 76b062336..c807ed58f 100644 --- a/src/freertos_drivers/common/Devtab.hxx +++ b/src/freertos_drivers/common/Devtab.hxx @@ -62,6 +62,7 @@ struct File off_t offset; /**< current offset within file */ int flags; /**< open flags */ uint8_t inuse : 1; /**< true if this is an open fd. */ + uint8_t inshdn : 1; /**< true if this fd is in shutdown. */ uint8_t device : 1; /**< true if this is a device, false if file system */ uint8_t dir : 1; /**< true if this is a directory, else false */ uint8_t dirty : 1; /**< true if this file is dirty and needs flush */ diff --git a/src/freertos_drivers/common/Fileio.cxx b/src/freertos_drivers/common/Fileio.cxx index 2ebd83206..d6c64b692 100644 --- a/src/freertos_drivers/common/Fileio.cxx +++ b/src/freertos_drivers/common/Fileio.cxx @@ -51,6 +51,7 @@ int FileIO::fd_alloc(void) if (files[i].inuse == false) { files[i].inuse = true; + files[i].inshdn = false; files[i].device = true; files[i].dir = false; files[i].dirty = false; @@ -85,7 +86,7 @@ File* FileIO::file_lookup(int fd) errno = EBADF; return nullptr; } - if (files[fd].inuse == 0) + if (files[fd].inuse == 0 || files[fd].inshdn == 1) { errno = EBADF; return nullptr;