Skip to content

Commit d34995a

Browse files
committed
Merge bitcoin#10038: Add mallocinfo mode to getmemoryinfo RPC
e141aa4 Add mallocinfo mode to `getmemoryinfo` RPC (Wladimir J. van der Laan) Tree-SHA512: e778631765c29b3b5fb94eb66e5f50a8f108a234891bdcc4883f1e6e2fdd223f7660fad987eb2d7cbda5b800482d78adc1a309a3f6f83a84c556af43ebee2ed7
2 parents 7c7ddd9 + e141aa4 commit d34995a

File tree

2 files changed

+54
-7
lines changed

2 files changed

+54
-7
lines changed

configure.ac

+7
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,13 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]],
566566
[ AC_MSG_RESULT(no)]
567567
)
568568

569+
dnl Check for malloc_info (for memory statistics information in getmemoryinfo)
570+
AC_MSG_CHECKING(for getmemoryinfo)
571+
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <malloc.h>]],
572+
[[ int f = malloc_info(0, NULL); ]])],
573+
[ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MALLOC_INFO, 1,[Define this symbol if you have malloc_info]) ],
574+
[ AC_MSG_RESULT(no)]
575+
)
569576

570577
AC_MSG_CHECKING([for visibility attribute])
571578
AC_LINK_IFELSE([AC_LANG_SOURCE([

src/rpc/misc.cpp

+47-7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#endif
2121

2222
#include <stdint.h>
23+
#ifdef HAVE_MALLOC_INFO
24+
#include <malloc.h>
25+
#endif
2326

2427
#include <boost/assign/list_of.hpp>
2528

@@ -485,16 +488,39 @@ static UniValue RPCLockedMemoryInfo()
485488
return obj;
486489
}
487490

491+
#ifdef HAVE_MALLOC_INFO
492+
static std::string RPCMallocInfo()
493+
{
494+
char *ptr = nullptr;
495+
size_t size = 0;
496+
FILE *f = open_memstream(&ptr, &size);
497+
if (f) {
498+
malloc_info(0, f);
499+
fclose(f);
500+
if (ptr) {
501+
std::string rv(ptr, size);
502+
free(ptr);
503+
return rv;
504+
}
505+
}
506+
return "";
507+
}
508+
#endif
509+
488510
UniValue getmemoryinfo(const JSONRPCRequest& request)
489511
{
490512
/* Please, avoid using the word "pool" here in the RPC interface or help,
491513
* as users will undoubtedly confuse it with the other "memory pool"
492514
*/
493-
if (request.fHelp || request.params.size() != 0)
515+
if (request.fHelp || request.params.size() > 1)
494516
throw std::runtime_error(
495-
"getmemoryinfo\n"
517+
"getmemoryinfo (\"mode\")\n"
496518
"Returns an object containing information about memory usage.\n"
497-
"\nResult:\n"
519+
"Arguments:\n"
520+
"1. \"mode\" determines what kind of information is returned. This argument is optional, the default mode is \"stats\".\n"
521+
" - \"stats\" returns general statistics about memory usage in the daemon.\n"
522+
" - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+).\n"
523+
"\nResult (mode \"stats\"):\n"
498524
"{\n"
499525
" \"locked\": { (json object) Information about locked memory manager\n"
500526
" \"used\": xxxxx, (numeric) Number of bytes used\n"
@@ -505,13 +531,27 @@ UniValue getmemoryinfo(const JSONRPCRequest& request)
505531
" \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
506532
" }\n"
507533
"}\n"
534+
"\nResult (mode \"mallocinfo\"):\n"
535+
"\"<malloc version=\"1\">...\"\n"
508536
"\nExamples:\n"
509537
+ HelpExampleCli("getmemoryinfo", "")
510538
+ HelpExampleRpc("getmemoryinfo", "")
511539
);
512-
UniValue obj(UniValue::VOBJ);
513-
obj.push_back(Pair("locked", RPCLockedMemoryInfo()));
514-
return obj;
540+
541+
std::string mode = (request.params.size() < 1 || request.params[0].isNull()) ? "stats" : request.params[0].get_str();
542+
if (mode == "stats") {
543+
UniValue obj(UniValue::VOBJ);
544+
obj.push_back(Pair("locked", RPCLockedMemoryInfo()));
545+
return obj;
546+
} else if (mode == "mallocinfo") {
547+
#ifdef HAVE_MALLOC_INFO
548+
return RPCMallocInfo();
549+
#else
550+
throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo is only available when compiled with glibc 2.10+");
551+
#endif
552+
} else {
553+
throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown mode " + mode);
554+
}
515555
}
516556

517557
UniValue echo(const JSONRPCRequest& request)
@@ -531,7 +571,7 @@ static const CRPCCommand commands[] =
531571
{ // category name actor (function) okSafeMode
532572
// --------------------- ------------------------ ----------------------- ----------
533573
{ "control", "getinfo", &getinfo, true, {} }, /* uses wallet if enabled */
534-
{ "control", "getmemoryinfo", &getmemoryinfo, true, {} },
574+
{ "control", "getmemoryinfo", &getmemoryinfo, true, {"mode"} },
535575
{ "util", "validateaddress", &validateaddress, true, {"address"} }, /* uses wallet if enabled */
536576
{ "util", "createmultisig", &createmultisig, true, {"nrequired","keys"} },
537577
{ "util", "verifymessage", &verifymessage, true, {"address","signature","message"} },

0 commit comments

Comments
 (0)