From: Volker Lendecke Date: Fri, 30 Aug 2019 13:08:40 +0000 (+0200) Subject: messaging: Do POOL_USAGE via a socket X-Git-Tag: talloc-2.3.1~766 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bc4e8b1abaf8431d1f507107cf60e57da75c0bef;p=thirdparty%2Fsamba.git messaging: Do POOL_USAGE via a socket This makes debugging run-away processes much more efficient and even possible at all: If the pool-usage output is more than 256MB, the previous code could not realloc it and threw it away. Also, it is not helpful for an already huge process to allocate even more. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Wed Sep 18 21:27:30 UTC 2019 on sn-devel-184 --- diff --git a/source3/lib/tallocmsg.c b/source3/lib/tallocmsg.c index 9be1bf58a3c..42cbe2d9c02 100644 --- a/source3/lib/tallocmsg.c +++ b/source3/lib/tallocmsg.c @@ -18,92 +18,69 @@ #include "includes.h" #include "messages.h" -#include "lib/util/talloc_report.h" +#include "lib/util/talloc_report_printf.h" #ifdef HAVE_MALLINFO #include #endif /* HAVE_MALLINFO */ - /** - * Prepare memory allocation report based on mallinfo() - **/ -static char *get_mallinfo_report(void *mem_ctx) +static bool pool_usage_filter(struct messaging_rec *rec, void *private_data) { - char *report = NULL; -#ifdef HAVE_MALLINFO - struct mallinfo mi; - - mi = mallinfo(); - report = talloc_asprintf(mem_ctx, - "mallinfo:\n" - " arena: %d\n" - " ordblks: %d\n" - " smblks: %d\n" - " hblks: %d\n" - " hblkhd: %d\n" - " usmblks: %d\n" - " fsmblks: %d\n" - " uordblks: %d\n" - " fordblks: %d\n" - " keepcost: %d\n", - mi.arena, - mi.ordblks, - mi.smblks, - mi.hblks, - mi.hblkhd, - mi.usmblks, - mi.fsmblks, - mi.uordblks, - mi.fordblks, - mi.keepcost); -#endif /* HAVE_MALLINFO */ + if (rec->msg_type != MSG_REQ_POOL_USAGE) { + return false; + } + + DBG_DEBUG("Got MSG_REQ_POOL_USAGE\n"); - return report; + if (rec->num_fds != 1) { + DBG_DEBUG("Got %"PRIu8" fds, expected one\n", rec->num_fds); + return false; + } + + return true; } -/** - * Respond to a POOL_USAGE message by sending back string form of memory - * usage stats. - **/ -static void msg_pool_usage(struct messaging_context *msg_ctx, - void *private_data, - uint32_t msg_type, - struct server_id src, - DATA_BLOB *data) -{ - char *report = NULL; - char *mreport = NULL; - int iov_size = 0; - struct iovec iov[2]; - SMB_ASSERT(msg_type == MSG_REQ_POOL_USAGE); - DEBUG(2,("Got POOL_USAGE\n")); +static void msg_pool_usage_do(struct tevent_req *req) +{ + struct messaging_context *msg_ctx = tevent_req_callback_data( + req, struct messaging_context); + struct messaging_rec *rec = NULL; + FILE *f = NULL; + int ret; - report = talloc_report_str(msg_ctx, NULL); - if (report != NULL) { - iov[iov_size].iov_base = report; - iov[iov_size].iov_len = talloc_get_size(report) - 1; - iov_size++; + ret = messaging_filtered_read_recv(req, talloc_tos(), &rec); + TALLOC_FREE(req); + if (ret != 0) { + DBG_DEBUG("messaging_filtered_read_recv returned %s\n", + strerror(ret)); + return; } - mreport = get_mallinfo_report(msg_ctx); - if (mreport != NULL) { - iov[iov_size].iov_base = mreport; - iov[iov_size].iov_len = talloc_get_size(mreport) - 1; - iov_size++; + f = fdopen(rec->fds[0], "w"); + if (f == NULL) { + close(rec->fds[0]); + TALLOC_FREE(rec); + DBG_DEBUG("fdopen failed: %s\n", strerror(errno)); } - if (iov_size) { - messaging_send_iov(msg_ctx, - src, - MSG_POOL_USAGE, - iov, - iov_size, - NULL, - 0); - } + TALLOC_FREE(rec); + + talloc_full_report_printf(NULL, f); + + fclose(f); + f = NULL; - TALLOC_FREE(report); - TALLOC_FREE(mreport); + req = messaging_filtered_read_send( + msg_ctx, + messaging_tevent_context(msg_ctx), + msg_ctx, + pool_usage_filter, + NULL); + if (req == NULL) { + DBG_WARNING("messaging_filtered_read_send failed\n"); + return; + } + tevent_req_set_callback(req, msg_pool_usage_do, msg_ctx); } /** @@ -111,6 +88,18 @@ static void msg_pool_usage(struct messaging_context *msg_ctx, **/ void register_msg_pool_usage(struct messaging_context *msg_ctx) { - messaging_register(msg_ctx, NULL, MSG_REQ_POOL_USAGE, msg_pool_usage); + struct tevent_req *req = NULL; + + req = messaging_filtered_read_send( + msg_ctx, + messaging_tevent_context(msg_ctx), + msg_ctx, + pool_usage_filter, + NULL); + if (req == NULL) { + DBG_WARNING("messaging_filtered_read_send failed\n"); + return; + } + tevent_req_set_callback(req, msg_pool_usage_do, msg_ctx); DEBUG(2, ("Registered MSG_REQ_POOL_USAGE\n")); -} +} diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c index 1435cc57d0a..35cb7d39a02 100644 --- a/source3/utils/smbcontrol.c +++ b/source3/utils/smbcontrol.c @@ -125,18 +125,6 @@ static void print_pid_string_cb(struct messaging_context *msg, num_replies++; } -/* Message handler callback that displays a string on stdout */ - -static void print_string_cb(struct messaging_context *msg, - void *private_data, - uint32_t msg_type, - struct server_id pid, - DATA_BLOB *data) -{ - printf("%*s", (int)data->length, (const char *)data->data); - num_replies++; -} - /* Send no message. Useful for testing. */ static bool do_noop(struct tevent_context *ev_ctx, @@ -861,31 +849,32 @@ static bool do_ip_dropped(struct tevent_context *ev_ctx, static bool do_poolusage(struct tevent_context *ev_ctx, struct messaging_context *msg_ctx, - const struct server_id pid, + const struct server_id dst, const int argc, const char **argv) { + pid_t pid = procid_to_pid(&dst); + int stdout_fd = 1; + if (argc != 1) { fprintf(stderr, "Usage: smbcontrol pool-usage\n"); return False; } - messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb); - - /* Send a message and register our interest in a reply */ - - if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0)) - return False; - - wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0); - - /* No replies were received within the timeout period */ - - if (num_replies == 0) - printf("No replies received\n"); + if (pid == 0) { + fprintf(stderr, "Can only send to a specific PID\n"); + return false; + } - messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL); + messaging_send_iov( + msg_ctx, + dst, + MSG_REQ_POOL_USAGE, + NULL, + 0, + &stdout_fd, + 1); - return num_replies; + return true; } /* Fetch and print the ringbuf log */ diff --git a/source3/wscript_build b/source3/wscript_build index b93ee6ff796..6707b4bb146 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -429,7 +429,7 @@ bld.SAMBA3_SUBSYSTEM('samba3core', server_id_db messages_util messages_dgm - talloc_report + talloc_report_printf access TDB_LIB ''') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index e5f399f033e..ec7f5f7bad7 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -35,7 +35,7 @@ #include "../lib/util/tevent_ntstatus.h" #include "lib/param/param.h" #include "lib/util/server_id_db.h" -#include "lib/util/talloc_report.h" +#include "lib/util/talloc_report_printf.h" #include "../source3/lib/messages_dgm.h" #include "../source3/lib/messages_dgm_ref.h" #include "../source3/lib/messages_util.h" @@ -108,21 +108,21 @@ static void pool_message(struct imessaging_context *msg, int *fds, DATA_BLOB *data) { - char *report; + FILE *f = NULL; - if (num_fds != 0) { + if (num_fds != 1) { DBG_WARNING("Received %zu fds, ignoring message\n", num_fds); return; } - report = talloc_report_str(msg, NULL); - - if (report != NULL) { - DATA_BLOB blob = { .data = (uint8_t *)report, - .length = talloc_get_size(report) - 1}; - imessaging_send(msg, src, MSG_POOL_USAGE, &blob); + f = fdopen(fds[0], "w"); + if (f == NULL) { + DBG_DEBUG("fopen failed: %s\n", strerror(errno)); + return; } - talloc_free(report); + + talloc_full_report_printf(NULL, f); + fclose(f); } static void ringbuf_log_msg(struct imessaging_context *msg,