Skip to content
Snippets Groups Projects
Commit 8fcda650 authored by Nat Goodspeed's avatar Nat Goodspeed
Browse files

CHOP-753: Add classic-C-style diagnostics around popen("vm_stat").

On Mac, where LLMemoryInfo relies on a child process rather than any sort of
internal system API, try to produce more informative LL_WARNS output if
popen() fails to run vm_stat, or if vm_stat terminates with nonzero rc.
parent 607f60d6
No related branches found
No related tags found
No related merge requests found
...@@ -68,6 +68,8 @@ using namespace llsd; ...@@ -68,6 +68,8 @@ using namespace llsd;
# include <sys/utsname.h> # include <sys/utsname.h>
# include <stdint.h> # include <stdint.h>
# include <Carbon/Carbon.h> # include <Carbon/Carbon.h>
# include <sys/wait.h>
# include <string.h>
#elif LL_LINUX #elif LL_LINUX
# include <errno.h> # include <errno.h>
# include <sys/utsname.h> # include <sys/utsname.h>
...@@ -979,11 +981,23 @@ LLSD LLMemoryInfo::loadStatsArray() ...@@ -979,11 +981,23 @@ LLSD LLMemoryInfo::loadStatsArray()
} }
FILE* pout = popen("vm_stat 2>&1", "r"); FILE* pout = popen("vm_stat 2>&1", "r");
if (! pout) if (! pout) // popen() couldn't run vm_stat
{ {
LL_WARNS("LLMemoryInfo") << "Unable to collect vm_stat memory information" << LL_ENDL; // Save errno right away.
int popen_errno(errno);
LL_WARNS("LLMemoryInfo") << "Unable to collect vm_stat memory information: ";
char buffer[256];
if (0 == strerror_r(popen_errno, buffer, sizeof(buffer)))
{
LL_CONT << buffer;
}
else
{
LL_CONT << "errno " << popen_errno;
}
LL_CONT << LL_ENDL;
} }
else else // popen() launched vm_stat
{ {
// Mach Virtual Memory Statistics: (page size of 4096 bytes) // Mach Virtual Memory Statistics: (page size of 4096 bytes)
// Pages free: 462078. // Pages free: 462078.
...@@ -1097,7 +1111,47 @@ LLSD LLMemoryInfo::loadStatsArray() ...@@ -1097,7 +1111,47 @@ LLSD LLMemoryInfo::loadStatsArray()
LL_WARNS("LLMemoryInfo") << "unrecognized vm_stat line: " << line << LL_ENDL; LL_WARNS("LLMemoryInfo") << "unrecognized vm_stat line: " << line << LL_ENDL;
} }
} }
fclose(pout); int status(pclose(pout));
if (status == -1) // pclose() couldn't retrieve rc
{
// Save errno right away.
int pclose_errno(errno);
// The ECHILD error happens so frequently that unless filtered,
// the warning below spams the log file. This is too bad, because
// sometimes the logic above fails to produce any output derived
// from vm_stat, but we've been unable to observe any specific
// error indicating the problem.
if (pclose_errno != ECHILD)
{
LL_WARNS("LLMemoryInfo") << "Unable to obtain vm_stat termination code: ";
char buffer[256];
if (0 == strerror_r(pclose_errno, buffer, sizeof(buffer)))
{
LL_CONT << buffer;
}
else
{
LL_CONT << "errno " << pclose_errno;
}
LL_CONT << LL_ENDL;
}
}
else // pclose() retrieved rc; analyze
{
if (WIFEXITED(status))
{
int rc(WEXITSTATUS(status));
if (rc != 0)
{
LL_WARNS("LLMemoryInfo") << "vm_stat terminated with rc " << rc << LL_ENDL;
}
}
else if (WIFSIGNALED(status))
{
LL_WARNS("LLMemoryInfo") << "vm_stat terminated by signal " << WTERMSIG(status)
<< LL_ENDL;
}
}
} }
#elif LL_SOLARIS #elif LL_SOLARIS
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment