messaging: Do POOL_USAGE via a socket
authorVolker Lendecke <vl@samba.org>
Fri, 30 Aug 2019 13:08:40 +0000 (15:08 +0200)
committerJeremy Allison <jra@samba.org>
Wed, 18 Sep 2019 21:27:30 +0000 (21:27 +0000)
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 <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Wed Sep 18 21:27:30 UTC 2019 on sn-devel-184

source3/lib/tallocmsg.c
source3/utils/smbcontrol.c
source3/wscript_build
source4/lib/messaging/messaging.c

index 9be1bf58a3c3168312a5bd90fbce884fea7b1f1f..42cbe2d9c025600dcd6084aa41cdffa0069a2cc9 100644 (file)
 
 #include "includes.h"
 #include "messages.h"
-#include "lib/util/talloc_report.h"
+#include "lib/util/talloc_report_printf.h"
 #ifdef HAVE_MALLINFO
 #include <malloc.h>
 #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"));
-}      
+}
index 1435cc57d0a23b8cfb893420d20a7ba69454ced8..35cb7d39a02196cce0cd2ee4b37c980c70cef6a3 100644 (file)
@@ -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 <dest> 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 */
index b93ee6ff796b9cb84472eb65b23cbbc1386b0fb0..6707b4bb1464818b7988881e884615533493ad7e 100644 (file)
@@ -429,7 +429,7 @@ bld.SAMBA3_SUBSYSTEM('samba3core',
                         server_id_db
                         messages_util
                         messages_dgm
-                        talloc_report
+                        talloc_report_printf
                         access
                         TDB_LIB
                         ''')
index e5f399f033e629ad2d95687de1c525c127201759..ec7f5f7bad7b4e737f40d7e72d7e87f24e923cd1 100644 (file)
@@ -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,