The rate filter is potentially opening fds in one thread while another
thread is processing a fork() in the plugin. Although the file is not
open for long, we MUST atomically use CLOEXEC to avoid fd leaks. This
one is a bit harder to observe using only the sh plugin, because the
window is small; you'll have better success at catching the leak by
using gdb or recompiling code to insert strategic sleeps.
Although fopen("re") is not required by POSIX yet, it has been
documented for several years [1] and many platforms already support
it. Failure to support it will not be seen at compile time, and it's
hard to state whether our unit tests will catch it; thus, I decided to
also add a comment to another use of fopen("re") that is much more
likely to show if we hit a problematic system.
[1]
http://austingroupbugs.net/view.php?id=411
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
filters/rate/rate.c | 2 +-
server/utils.c | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/filters/rate/rate.c b/filters/rate/rate.c
index f8dda0b0..9476a27f 100644
--- a/filters/rate/rate.c
+++ b/filters/rate/rate.c
@@ -204,7 +204,7 @@ maybe_adjust (const char *file, struct bucket *bucket, pthread_mutex_t
*lock)
if (!file) return;
- fp = fopen (file, "r");
+ fp = fopen (file, "re");
if (fp == NULL)
return; /* this is not an error */
diff --git a/server/utils.c b/server/utils.c
index eabef200..d7e202ec 100644
--- a/server/utils.c
+++ b/server/utils.c
@@ -236,6 +236,10 @@ nbdkit_read_password (const char *value, char **password)
}
/* Read password from a file. */
+ /* Note: If the unit test for this fails because fopen("re") is
+ * unsupported by a given system, you must also fix the rate filter
+ * to use a similar workaround.
+ */
else if (value[0] == '+') {
fp = fopen (&value[1], "re");
if (fp == NULL) {
--
2.20.1