filesystem: provide kqueue-based impl of Watcher#1363
filesystem: provide kqueue-based impl of Watcher#1363mattklein123 merged 6 commits intoenvoyproxy:masterfrom
Conversation
mattklein123
left a comment
There was a problem hiding this comment.
Thanks very much for splitting this out. Few small comments. Generally LGTM.
bazel/envoy_build_system.bzl
Outdated
| linkstatic = 1, | ||
| linkstamp = linkstamp, | ||
| ) | ||
| strip_include_prefix = strip_include_prefix, |
| reinterpret_cast<void*>(watch_fd)); | ||
|
|
||
| if (kevent(queue_, &event, 1, NULL, 0, NULL) == -1) { | ||
| throw EnvoyException( |
There was a problem hiding this comment.
watch->fd_ will leak here when you throw and in other cases. Can you add close() to the destructor of FileWatch, then you can make overall destruction simpler.
|
|
||
| WatcherImpl::FileWatchPtr WatcherImpl::addWatch_(const std::string& path, uint32_t events, | ||
| Watcher::OnChangedCb cb, bool pathMustExist) { | ||
| bool watchingDir = false; |
There was a problem hiding this comment.
nit: all variables should be snake_case (there are other examples).
| flags = NOTE_DELETE | NOTE_WRITE; | ||
| } | ||
|
|
||
| struct kevent event; |
There was a problem hiding this comment.
nit: struct not needed in C++ code.
There was a problem hiding this comment.
The function kevent hides the struct, so I think it's necessary here.
| void onKqueueEvent(); | ||
| FileWatchPtr addWatch_(const std::string& path, uint32_t events, Watcher::OnChangedCb cb, | ||
| bool pathMustExist); | ||
| void removeWatch_(FileWatchPtr& watch); |
There was a problem hiding this comment.
nit: removeWatch_ doesn't really need the trailing _.
| fmt::format("unable to add filesystem watch for file {}: {}", path, strerror(event.data))); | ||
| } | ||
|
|
||
| log_debug("added watch for file: '{}' fd: {}", path, watch_fd); |
There was a problem hiding this comment.
Please switch all of these to ENVOY_LOG macros.
htuch
left a comment
There was a problem hiding this comment.
What's the test coverage results like on the kqueue implementation?
|
Coverage is about 85%. Everything but the error guards. |
alyssawilk
left a comment
There was a problem hiding this comment.
Looks good overall, and very useful comments, thanks!
|
|
||
| #include "common/common/assert.h" | ||
| #include "common/common/thread.h" | ||
| #include "common/filesystem/filesystem_impl.h" |
There was a problem hiding this comment.
Google include order has a special case for foo.cc including foo.h as the first line, so I think you can revert most of the include order changes.
I think the fix_format script will catch this for you, so it's worth running it locally and seeing what else it turns up!
There was a problem hiding this comment.
I could swear the fix script did this for me. Weird.
|
|
||
| while (true) { | ||
| uint32_t events = 0; | ||
| int nevents = kevent(queue_, NULL, 0, &event, 1, &nullts); |
|
|
||
| void WatcherImpl::removeWatch(FileWatchPtr& watch) { | ||
| int fd = watch->fd_; | ||
| watches_.erase(fd); |
There was a problem hiding this comment.
I was surprised that one didn't have to unregister but kevent docs note "Events which are attached to file descriptors are automatically deleted on the last close of the descriptor."
Can you add a comment here that the deletion will close the fd and result in automatic unregistration?
| int watch_fd = reinterpret_cast<std::intptr_t>(event.udata); | ||
|
|
||
| FileWatchPtr file = watches_[watch_fd]; | ||
| if (file == nullptr) { |
There was a problem hiding this comment.
I'm all for this paranoia check but when can this happen? Should it be an ASSERT that it does not?
| removeWatch(file); | ||
| file = new_file; | ||
|
|
||
| events |= Events::MovedTo; |
There was a problem hiding this comment.
Aren't the events in this case the events for the directory? Do we want to |= or overwrite entirely?
There was a problem hiding this comment.
events is only ever 0 or Events::MovedTo (which is the only value defined in include/envoy/filesystem/filesystem.h). The inotify implementation does this as well. I assumed it was because someone expected to add more event types some day.
| file->callback_(events); | ||
| } | ||
|
|
||
| ENVOY_LOG(debug, "notification: fd: {} flags: {:x} file: {}", file->fd_, event.fflags, |
There was a problem hiding this comment.
Given the callback may trigger a bunch of logs on its own, you may want to bump this log line up before so you get the log about the event on the file before all the things triggered by that event.
alyssawilk
left a comment
There was a problem hiding this comment.
Looking good - just two more nits on my end
| typedef std::shared_ptr<FileWatch> FileWatchPtr; | ||
|
|
||
| void onKqueueEvent(); | ||
| FileWatchPtr addWatch_(const std::string& path, uint32_t events, Watcher::OnChangedCb cb, |
There was a problem hiding this comment.
I don't think this needs the trailing _ either
| int rc = symlink(TestEnvironment::temporaryPath("envoy_test/watcher_target").c_str(), | ||
| TestEnvironment::temporaryPath("envoy_test/watcher_new_link").c_str()); | ||
| RELEASE_ASSERT(0 == rc); | ||
| UNREFERENCED_PARAMETER(rc); |
There was a problem hiding this comment.
Nice additions!
I wonder if the tests you're modeling predated gtest? I think you can replace these two lines with
ASSERT_EQ(0, rc); here and below and it'll be more consistent with tests elsewhere in the code base
| if (file->watching_dir_) { | ||
| if (event.fflags & NOTE_DELETE) { | ||
| // directory was deleted | ||
| removeWatch(file); |
There was a problem hiding this comment.
Does one of the tests cover this case?
There was a problem hiding this comment.
Latest commit adds a test that hits this line.
|
|
||
| #include "common/common/assert.h" | ||
| #include "common/common/utility.h" | ||
| #include "common/filesystem/watcher_impl.h" |
There was a problem hiding this comment.
Sorry I missed this on the last pass but I think this include change still needs to be reverted
There was a problem hiding this comment.
I'm guessing the new inotify prefix breaks the header format script (since this passed tests). I think it's probably not worth worrying about but we can potentially make a note to try to make the script deal with this somehow (by having it understand the strip stuff).
There was a problem hiding this comment.
If it works for you, it works for me :-)
| if (file->watching_dir_) { | ||
| if (event.fflags & NOTE_DELETE) { | ||
| // directory was deleted | ||
| removeWatch(file); |
mattklein123
left a comment
There was a problem hiding this comment.
Thank you @zuercher this looks great! Thanks for adding new tests also and fixing missing coverage. This works for me. Will hold off on merging in case @alyssawilk has any further comments/thoughts on the header order issue.
|
LGTM on my front! |
…oxy#1364) Automatic merge from submit-queue. Remove JWT headers consumed by Istio authn and mixer filters **What this PR does / why we need it**: This PR removes the JWT headers after they have been consumed by Istio authn and mixer filters. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes envoyproxy#1363 **Special notes for your reviewer**: **Release note**: ```release-note ```
Signed-off-by: Jose Nino <jnino@lyft.com> Signed-off-by: JP Simard <jp@jpsim.com>
Signed-off-by: Jose Nino <jnino@lyft.com> Signed-off-by: JP Simard <jp@jpsim.com>
(Split out of #1348, part of fixes for #128).
This implementation watches the given file, if it exists. Otherwise it watches the directory for writes and then checks to see if the directory modification caused the file to appear.