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@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