-
Notifications
You must be signed in to change notification settings - Fork 701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: File descriptor leaks for eventfd and timerfd_create #1158
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,6 +132,7 @@ namespace Pistache | |
{ | ||
public: | ||
NotifyFd(); | ||
~NotifyFd(); | ||
|
||
Polling::Tag bind(Polling::Epoll& poller); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,14 @@ | |
#include <string> | ||
#include <thread> | ||
|
||
#if __has_include(<filesystem>) | ||
#include <filesystem> | ||
namespace filesystem = std::filesystem; | ||
#else | ||
#include <experimental/filesystem> | ||
namespace filesystem = std::experimental::filesystem; | ||
#endif | ||
|
||
#include "tcp_client.h" | ||
|
||
using namespace Pistache; | ||
|
@@ -1043,3 +1051,40 @@ TEST(http_server_test, server_with_content_encoding_deflate) | |
ASSERT_EQ(originalUncompressedData, newlyDecompressedData); | ||
} | ||
#endif | ||
|
||
TEST(http_server_test, http_server_is_not_leaked) | ||
{ | ||
const auto number_of_fds = [] { | ||
using filesystem::directory_iterator; | ||
const filesystem::path fds_dir { "/proc/self/fd" }; | ||
|
||
if (!filesystem::exists(fds_dir)) | ||
{ | ||
return directory_iterator::difference_type(0); | ||
} | ||
|
||
return std::distance(directory_iterator(fds_dir), directory_iterator {}); | ||
}; | ||
|
||
const auto fds_before = number_of_fds(); | ||
const Pistache::Address address("localhost", Pistache::Port(0)); | ||
|
||
auto server = std::make_unique<Http::Endpoint>(address); | ||
auto flags = Tcp::Options::ReuseAddr; | ||
auto server_opts = Http::Endpoint::options().flags(flags).threads(4); | ||
server->init(server_opts); | ||
server->setHandler(Http::make_handler<PingHandler>()); | ||
server->serveThreaded(); | ||
server->shutdown(); | ||
server.reset(); | ||
|
||
if (fds_before > 0) | ||
{ | ||
const auto fds_after = number_of_fds(); | ||
ASSERT_EQ(fds_before, fds_after); | ||
} | ||
else | ||
{ | ||
std::cout << "NOTE: Please use Valgrind with '--track-fds=yes' option for this test" << std::endl; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tyler92, I am a bit concerned about this. Does the user need to run the unit test in valgrind(1) in order to verify that it passed? The reason I ask is it would be cumbersome for a user to have to manually do that, as opposed to the build environment automatically doing that. If it can't do that, then if the test fails we'll never know during CI. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with you. It's related to the first question from another thread. The logic here is the following - we need to handle the case when our "leak detector" fails. In this case, we can do one of the following: fail the test, pass the test, or pass with a warning. I chose the last option, but if we have full confidence in this leak detection approach, we may fail the test. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we don't have full confidence yet in this approach and it might need refactoring. You might need to modify the build environment itself to ensure that the test is run via There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kiplingw Probably there is a misunderstanding. When I said "leak detection approach", I meant not valgrind, but checking file descriptors count. Now I suggest removing anything about Valgrind in my test, and it will look like this: TEST(http_server_test, http_server_is_not_leaked)
{
const auto number_of_fds = [] {
using filesystem::directory_iterator;
const filesystem::path fds_dir { "/proc/self/fd" };
if (!filesystem::exists(fds_dir))
{
return directory_iterator::difference_type(0);
}
return std::distance(directory_iterator(fds_dir), directory_iterator {});
};
const auto fds_before = number_of_fds();
ASSERT_GT(fds_before, 0);
// ...
const auto fds_after = number_of_fds();
ASSERT_EQ(fds_before, fds_after); Valgrind was a fallback option in my original idea, but it has downsides. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dennisjenkins75, thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you probably intend to remove the Valgrind fallback this isn't very relevant, but in general when skipping tests in GoogleTest you should use |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
0.2.3.20231022 | ||
0.2.4.20231031 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
number_of_fds()
to return 0? gunit'smain()
does not close STDOUT nor STDERR, so there should always be at least two.4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/proc/self/fd
directory doesn't exist. I know that the library supports only Linux now, but I wasn't sure if I could make this assumption for unit tests. Do you recommend removing this check?