diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2011-07-11 14:24:28 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2011-07-11 14:24:28 -0400 |
commit | 8fcda650a71d4784dcb24e86b3fc59ad15bc6a2d (patch) | |
tree | f4bd2ede3282fa48be4197930498474db886fe3d /indra/llcommon | |
parent | 607f60d6f6ddf18e69b5106bbb6ef31b72ba78f2 (diff) |
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.
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/llsys.cpp | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 74a9a68dc8..9390fc170c 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -68,6 +68,8 @@ using namespace llsd; # include <sys/utsname.h> # include <stdint.h> # include <Carbon/Carbon.h> +# include <sys/wait.h> +# include <string.h> #elif LL_LINUX # include <errno.h> # include <sys/utsname.h> @@ -979,11 +981,23 @@ LLSD LLMemoryInfo::loadStatsArray() } 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) // Pages free: 462078. @@ -1097,7 +1111,47 @@ LLSD LLMemoryInfo::loadStatsArray() 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 |