/* Icinga 2 | (c) 2024 Icinga GmbH | GPLv2+ */ #include "base/defer.hpp" #include "remote/filterutility.hpp" #include "remote/httputility.hpp" #include "remote/mallocinfohandler.hpp" #include #include #include #ifdef HAVE_MALLOC_INFO # include # include #endif /* HAVE_MALLOC_INFO */ using namespace icinga; REGISTER_URLHANDLER("/v1/debug/malloc_info", MallocInfoHandler); bool MallocInfoHandler::HandleRequest( const WaitGroup::Ptr&, HttpRequest& request, HttpResponse& response, boost::asio::yield_context& ) { namespace http = boost::beast::http; if (request.Url()->GetPath().size() != 3) { return false; } if (request.method() != http::verb::get) { return false; } FilterUtility::CheckPermission(request.User(), "debug"); #ifndef HAVE_MALLOC_INFO response.SendJsonError(request.Params(), 501, "malloc_info(3) not available."); #else /* HAVE_MALLOC_INFO */ char* buf = nullptr; size_t bufSize = 0; FILE* f = nullptr; Defer release ([&f, &buf]() { if (f) { (void)fclose(f); } free(buf); }); f = open_memstream(&buf, &bufSize); if (!f) { auto error (errno); BOOST_THROW_EXCEPTION(posix_error() << boost::errinfo_api_function("open_memstream") << boost::errinfo_errno(error)); } if (malloc_info(0, f)) { auto error (errno); BOOST_THROW_EXCEPTION(posix_error() << boost::errinfo_api_function("malloc_info") << boost::errinfo_errno(error)); } auto closeErr (fclose(f)); f = nullptr; if (closeErr) { auto error (errno); BOOST_THROW_EXCEPTION(posix_error() << boost::errinfo_api_function("fclose") << boost::errinfo_errno(error)); } response.result(200); response.set(http::field::content_type, "application/xml"); response.body() << std::string(buf, bufSize); #endif /* HAVE_MALLOC_INFO */ return true; }