You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by qi...@apache.org on 2018/10/30 20:58:05 UTC
[mesos] 01/02: Fixed an early fd close in the cgroups event
notifier.
This is an automated email from the ASF dual-hosted git repository.
qianzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git
commit 610064942d4a75f16f045480ca9e3414d37f1ecc
Author: Benjamin Mahler <bm...@apache.org>
AuthorDate: Fri Oct 26 10:50:54 2018 +0800
Fixed an early fd close in the cgroups event notifier.
The cgroups event notifier was closing the eventfd while an
`io::read()` operation may be in progress. This can lead to
bugs where the fd gets re-used and read from a stale io::read.
Review: https://reviews.apache.org/r/69123/
---
src/linux/cgroups.cpp | 41 +++++++++++++++++++++++++++--------------
1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/src/linux/cgroups.cpp b/src/linux/cgroups.cpp
index 95efc1d..45dd5cf 100644
--- a/src/linux/cgroups.cpp
+++ b/src/linux/cgroups.cpp
@@ -1047,7 +1047,7 @@ public:
// uint64_t) from the event file, it indicates that an event has
// occurred.
reading = io::read(eventfd.get(), &data, sizeof(data));
- reading.onAny(defer(self(), &Listener::_listen));
+ reading->onAny(defer(self(), &Listener::_listen, lambda::_1));
}
return promise.get()->future();
@@ -1069,14 +1069,23 @@ protected:
void finalize() override
{
// Discard the nonblocking read.
- reading.discard();
+ if (reading.isSome()) {
+ reading->discard();
+ }
- // Unregister the eventfd if needed.
+ // Unregister the eventfd if needed. If there's a pending read,
+ // we must wait for it to finish.
if (eventfd.isSome()) {
- Try<Nothing> unregister = unregisterNotifier(eventfd.get());
- if (unregister.isError()) {
- LOG(ERROR) << "Failed to unregister eventfd: " << unregister.error();
- }
+ int fd = eventfd.get();
+
+ reading.getOrElse(Future<size_t>(0))
+ .onAny([fd]() {
+ Try<Nothing> unregister = unregisterNotifier(fd);
+ if (unregister.isError()) {
+ LOG(ERROR) << "Failed to unregister eventfd '" << fd << "'"
+ << ": " << unregister.error();
+ }
+ });
}
// TODO(chzhcn): Fail our promise only after 'reading' has
@@ -1089,11 +1098,15 @@ protected:
private:
// This function is called when the nonblocking read on the eventfd has
// result, either because the event has happened, or an error has occurred.
- void _listen()
+ void _listen(Future<size_t> read)
{
CHECK_SOME(promise);
+ CHECK_SOME(reading);
+
+ // Reset to none since we're no longer reading.
+ reading = None();
- if (reading.isReady() && reading.get() == sizeof(data)) {
+ if (read.isReady() && read.get() == sizeof(data)) {
promise.get()->set(data);
// After fulfilling the promise, reset to get ready for the next one.
@@ -1101,14 +1114,14 @@ private:
return;
}
- if (reading.isDiscarded()) {
+ if (read.isDiscarded()) {
error = Error("Reading eventfd stopped unexpectedly");
- } else if (reading.isFailed()) {
- error = Error("Failed to read eventfd: " + reading.failure());
+ } else if (read.isFailed()) {
+ error = Error("Failed to read eventfd: " + read.failure());
} else {
error = Error("Read less than expected. Expect " +
stringify(sizeof(data)) + " bytes; actual " +
- stringify(reading.get()) + " bytes");
+ stringify(read.get()) + " bytes");
}
// Inform failure and not listen again.
@@ -1121,7 +1134,7 @@ private:
const Option<string> args;
Option<Owned<Promise<uint64_t>>> promise;
- Future<size_t> reading;
+ Option<Future<size_t>> reading;
Option<Error> error;
Option<int> eventfd;
uint64_t data; // The data read from the eventfd last time.