Module: check_mk
Branch: master
Commit: c0338ff8fe3a9138924ef1ad446637e5857f851b
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=c0338ff8fe3a91…
Author: Sergey Kipnis <sk(a)mathias-kettner.de>
Date: Fri Mar 22 13:37:22 2019 +0100
[CMK-1791] - memory leak in WMI fixed twice
- forgotten RAII introduced for WmiWrapper
- management of raw Windows handles are still based on the ON_OUT_OF_SCOPE. To be
refactored in the future
Change-Id: I4110bbec42dea10ecce4bdc842803021ad6c35f6
---
agents/wnx/src/common/wtools.cpp | 19 ++++++++++++++++---
agents/wnx/src/common/wtools.h | 9 +++++++++
agents/wnx/src/engine/providers/ps.cpp | 1 +
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/agents/wnx/src/common/wtools.cpp b/agents/wnx/src/common/wtools.cpp
index c31ce50..48b6015 100644
--- a/agents/wnx/src/common/wtools.cpp
+++ b/agents/wnx/src/common/wtools.cpp
@@ -1147,6 +1147,20 @@ bool WmiWrapper::open() noexcept { // Obtain the initial locator
to Windows
return true;
}
+// clean all
+void WmiWrapper::close() noexcept {
+ std::lock_guard lk(lock_);
+ if (locator_) {
+ locator_->Release();
+ locator_ = nullptr;
+ }
+
+ if (services_) {
+ services_->Release();
+ services_ = nullptr;
+ }
+}
+
// connect to the WMI namespace, root\\Something
// returns true when connect succeed or connect exists
// thread safe
@@ -1216,6 +1230,7 @@ bool WmiWrapper::impersonate() noexcept {
}
// tested implicitly
+// RETURNS RAW OBJECT
// returns nullptr on any error
IWbemClassObject* WmiGetNextObject(IEnumWbemClassObject* Enumerator) {
if (!Enumerator) {
@@ -1258,6 +1273,7 @@ std::wstring WmiWrapper::produceTable(
while (Enumerator) {
wmi_object = WmiGetNextObject(Enumerator);
if (!wmi_object) break;
+ ON_OUT_OF_SCOPE(wmi_object->Release());
// names
if (print_names_please) {
@@ -1276,9 +1292,6 @@ std::wstring WmiWrapper::produceTable(
auto raw = wtools::WmiStringFromObject(wmi_object, names);
if (!raw.empty()) result += raw + L"\n";
-
- wmi_object->Release();
- wmi_object = nullptr;
}
return result;
}
diff --git a/agents/wnx/src/common/wtools.h b/agents/wnx/src/common/wtools.h
index be983e6..d7e703a 100644
--- a/agents/wnx/src/common/wtools.h
+++ b/agents/wnx/src/common/wtools.h
@@ -888,6 +888,14 @@ IWbemClassObject* WmiGetNextObject(IEnumWbemClassObject*
Enumerator);
// the class is thread safe(theoretisch)
class WmiWrapper {
public:
+ WmiWrapper() : locator_(nullptr), services_(nullptr) {}
+
+ WmiWrapper(const WmiWrapper&) = delete;
+ WmiWrapper& operator=(const WmiWrapper&) = delete;
+ WmiWrapper(WmiWrapper&&) = delete;
+ WmiWrapper& operator=(WmiWrapper&&) = delete;
+
+ virtual ~WmiWrapper() { close(); }
// first call
bool open() noexcept;
@@ -912,6 +920,7 @@ public:
const std::wstring& Target) noexcept;
private:
+ void close() noexcept;
// build valid WQL query
static std::wstring makeQuery(const std::vector<std::wstring> Names,
const std::wstring& Target) noexcept;
diff --git a/agents/wnx/src/engine/providers/ps.cpp
b/agents/wnx/src/engine/providers/ps.cpp
index f04dc0a..c3f061a 100644
--- a/agents/wnx/src/engine/providers/ps.cpp
+++ b/agents/wnx/src/engine/providers/ps.cpp
@@ -271,6 +271,7 @@ std::string ProducePsWmi(bool FullPath) {
while (1) {
auto object = wtools::WmiGetNextObject(processes);
if (!object) break;
+ ON_OUT_OF_SCOPE(object->Release());
auto process_id = GetUint32AsInt64(object, L"ProcessId");