1414 * limitations under the License.
1515 */
1616
17+ #include < cerrno>
1718#include < cstring>
1819#include < dirent.h>
1920#include < fstream>
2021#include < iostream>
21- #include < stdio.h >
22+ #include < system_error >
2223
2324#include < DcgmLogging.h>
2425#include < DcgmStringHelpers.h>
@@ -105,7 +106,7 @@ dcgmPowerFileInfo_t DcgmSystemMonitor::GetCpuSocketFileIndex(const std::string &
105106
106107void DcgmSystemMonitor::PopulateSocketPowerMap (const std::string &baseDir)
107108{
108- static const std::string POWER_PATH_EXTENSION (" device/ " );
109+ static const std::string POWER_PATH_EXTENSION (" device" );
109110 static const std::string HWMON_DIR_NAME_START (" hwmon" );
110111 static const std::string POWER_USAGE_FILENAME (" power1_average" );
111112 static const std::string POWER_CAP_FILENAME (" power1_cap" );
@@ -117,59 +118,77 @@ void DcgmSystemMonitor::PopulateSocketPowerMap(const std::string &baseDir)
117118 return ;
118119 }
119120
120- DIR *dir = opendir (baseDir.c_str ());
121- struct dirent *entry;
121+ auto dirDeleter = [](DIR *dir) {
122+ if (dir != nullptr )
123+ {
124+ closedir (dir);
125+ dir = nullptr ;
126+ }
127+ };
128+
129+ auto dir = std::unique_ptr<DIR , decltype (dirDeleter)>(opendir (baseDir.c_str ()), dirDeleter);
130+ if (!dir)
131+ {
132+ auto syserr = std::system_error (errno, std::generic_category ());
133+ log_info (" Could not open directory '{}'" , baseDir);
134+ log_debug (" Got opendir error: ({}) {}" , syserr.code ().value (), syserr.what ());
135+ return ;
136+ }
137+
138+ struct dirent *entry = nullptr ;
122139
123- while ((entry = readdir (dir)) != nullptr )
140+ while ((entry = readdir (dir. get () )) != nullptr )
124141 {
125- if (entry->d_type == DT_DIR
126- || !strncmp (entry->d_name , HWMON_DIR_NAME_START .c_str (), HWMON_DIR_NAME_START .size ()))
142+ if (entry->d_type != DT_DIR || !std::string_view { entry->d_name }.starts_with (HWMON_DIR_NAME_START ))
143+ {
144+ continue ;
145+ }
146+
147+ auto pathPrefix = fmt::format (" {}/{}/{}" , baseDir, entry->d_name , POWER_PATH_EXTENSION );
148+
149+ std::string path = fmt::format (" {}/{}" , pathPrefix, POWER_OEM_INFO );
150+
151+ dcgmPowerFileInfo_t info = GetCpuSocketFileIndex (path);
152+ if (info.socketId == SYSMON_INVALID_SOCKET_ID )
153+ {
154+ log_debug (" Invalid socket ID. Skipping: '{}'" , entry->d_name );
155+ continue ;
156+ }
157+
158+ if (info.fileType == DCGM_POWER_USAGE_FILE )
127159 {
128- std::string path = fmt::format (" {}/{}/{}{}" , baseDir, entry->d_name , POWER_PATH_EXTENSION , POWER_OEM_INFO );
129- dcgmPowerFileInfo_t info = GetCpuSocketFileIndex (path);
130- if (info.socketId != SYSMON_INVALID_SOCKET_ID )
160+ // Something like: /sys/class/hwmon/hwmon4/device/power1_average
161+ auto usagePath = fmt::format (" {}/{}" , pathPrefix, POWER_USAGE_FILENAME );
162+
163+ if (info.fileSrc == DCGM_CPU_POWER_SOCKET_FILE )
164+ {
165+ m_cpuSocketToPowerUsagePath[info.socketId ] = std::move (usagePath);
166+ }
167+ else if (info.fileSrc == DCGM_SYSIO_POWER_SOCKET_FILE )
168+ {
169+ m_sysioSocketToPowerUsagePath[info.socketId ] = std::move (usagePath);
170+ }
171+ else if (info.fileSrc == DCGM_MODULE_POWER_SOCKET_FILE )
131172 {
132- if (info.fileType == DCGM_POWER_USAGE_FILE )
133- {
134- if (info.fileSrc == DCGM_CPU_POWER_SOCKET_FILE )
135- {
136- // Something like: /sys/class/hwmon/hwmon4/device/power1_average
137- m_cpuSocketToPowerUsagePath[info.socketId ] = fmt::format (
138- " {}/{}/{}{}" , baseDir, entry->d_name , POWER_PATH_EXTENSION , POWER_USAGE_FILENAME );
139- }
140- else if (info.fileSrc == DCGM_SYSIO_POWER_SOCKET_FILE )
141- {
142- // Something like: /sys/class/hwmon/hwmon4/device/power1_average
143- m_sysioSocketToPowerUsagePath[info.socketId ] = fmt::format (
144- " {}/{}/{}{}" , baseDir, entry->d_name , POWER_PATH_EXTENSION , POWER_USAGE_FILENAME );
145- }
146- else if (info.fileSrc == DCGM_MODULE_POWER_SOCKET_FILE )
147- {
148- // Something like: /sys/class/hwmon/hwmon4/device/power1_average
149- m_moduleSocketToPowerUsagePath[info.socketId ] = fmt::format (
150- " {}/{}/{}{}" , baseDir, entry->d_name , POWER_PATH_EXTENSION , POWER_USAGE_FILENAME );
151- }
152- else
153- {
154- log_debug (" File source invalid: '{}'" , info.fileSrc );
155- return ;
156- }
157- }
158- else if (info.fileType == DCGM_POWER_CAP_FILE )
159- {
160- // Something like: /sys/class/hwmon/hwmon3/device/power1_cap
161- m_socketToPowerCapPath[info.socketId ]
162- = fmt::format (" {}/{}/{}{}" , baseDir, entry->d_name , POWER_PATH_EXTENSION , POWER_CAP_FILENAME );
163- }
164- else
165- {
166- log_debug (" File type invalid: '{}'" , info.fileType );
167- return ;
168- }
173+ m_moduleSocketToPowerUsagePath[info.socketId ] = std::move (usagePath);
169174 }
175+ else
176+ {
177+ log_debug (" File source invalid: '{}'" , info.fileSrc );
178+ return ;
179+ }
180+ }
181+ else if (info.fileType == DCGM_POWER_CAP_FILE )
182+ {
183+ // Something like: /sys/class/hwmon/hwmon3/device/power1_cap
184+ m_socketToPowerCapPath[info.socketId ] = fmt::format (" {}/{}" , pathPrefix, POWER_CAP_FILENAME );
185+ }
186+ else
187+ {
188+ log_debug (" File type invalid: '{}'" , info.fileType );
189+ return ;
170190 }
171191 }
172- closedir (dir);
173192}
174193
175194double DcgmSystemMonitor::GetPowerValueFromFile (const std::string &path)
0 commit comments