]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cli/debug: show dev: add cmdline and version
authorValentine Krasnobaeva <vkrasnobaeva@haproxy.com>
Wed, 29 May 2024 09:27:21 +0000 (11:27 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 26 Jun 2024 05:38:21 +0000 (07:38 +0200)
'show dev' command is very convenient to obtain haproxy debugging information,
while process is run in container. Let's extend its output with version and
cmdline. cmdline is useful in a way, as it shows absolute binary path and its
arguments, because sometimes the person, who is debugging failing container is
not the same, who has created and deployed it.

argc and argv are stored in the exported global structure, because
feed_post_mortem() is added as a post check function callback in the
post_check_list. So we can't simply change the signature of
feed_post_mortem(), without breaking other post check callbacks APIs.

Parsers are not supposed to modify argv, so we can safely bypass its pointer
to debug_parse_cli_show_dev(), without copying all argument stings somewhere
in the heap or on stack.

include/haproxy/global-t.h
src/debug.c
src/haproxy.c

index 7665ef24d4c8fed742b3d0c92104dcef0e81876a..6e66a1d814e8bd20c84d846b66f43aba5890b2a7 100644 (file)
@@ -217,10 +217,15 @@ struct global {
        int thread_limit;               /* hard limit on the number of threads */
        int prealloc_fd;
        uchar clt_privileged_ports;     /* bitmask to allow client privileged ports exchanges per protocol */
-       /* 3-bytes hole */
+       unsigned char argc;             /* cast int argc to unsigned char in order to fill better the previous
+                                        * 3 bytes hole, it seems unreal, that oneday we could start with more
+                                        * than 255 arguments
+                                        */
+       /* 2-bytes hole */
        int cfg_curr_line;              /* line number currently being parsed */
        const char *cfg_curr_file;      /* config file currently being parsed or NULL */
        char *cfg_curr_section;         /* config section name currently being parsed or NULL */
+       char **argv;                    /* ptr to array with args */
 
        /* The info above is config stuff, it doesn't change during the process' life */
        /* A number of the elements below are updated by all threads in real time and
index 5f21f02711a65b1058dfcc2a7688af9dcb332c7a..a7626b18f94b4b44611e4f65168d3fcb9cddacdc 100644 (file)
@@ -47,6 +47,7 @@
 #include <haproxy/time.h>
 #include <haproxy/tools.h>
 #include <haproxy/trace.h>
+#include <haproxy/version.h>
 #include <import/ist.h>
 
 
@@ -114,6 +115,7 @@ struct post_mortem {
                gid_t boot_gid;
                struct rlimit limit_fd;  // RLIMIT_NOFILE
                struct rlimit limit_ram; // RLIMIT_DATA
+               char **argv;
 
 #if defined(USE_THREAD)
                struct {
@@ -121,6 +123,7 @@ struct post_mortem {
                        void *stack_top; // top of the stack
                } thread_info[MAX_THREADS];
 #endif
+               unsigned char argc;
        } process;
 
 #if defined(HA_HAVE_DUMP_LIBS)
@@ -498,12 +501,14 @@ static int debug_parse_cli_show_libs(char **args, char *payload, struct appctx *
 static int debug_parse_cli_show_dev(char **args, char *payload, struct appctx *appctx, void *private)
 {
        const char **build_opt;
+       int i;
 
        if (*args[2])
                return cli_err(appctx, "This command takes no argument.\n");
 
        chunk_reset(&trash);
 
+       chunk_appendf(&trash, "HAProxy version %s\n", haproxy_version);
        chunk_appendf(&trash, "Features\n  %s\n", build_features);
 
        chunk_appendf(&trash, "Build options\n");
@@ -545,8 +550,14 @@ static int debug_parse_cli_show_dev(char **args, char *payload, struct appctx *a
 
        chunk_appendf(&trash, "Process info\n");
        chunk_appendf(&trash, "  pid: %d\n", post_mortem.process.pid);
+       chunk_appendf(&trash, "  cmdline: ");
+       for (i = 0; i < post_mortem.process.argc; i++)
+               chunk_appendf(&trash, "%s ", post_mortem.process.argv[i]);
+       chunk_appendf(&trash, "\n");
        chunk_appendf(&trash, "  boot uid: %d\n", post_mortem.process.boot_uid);
+       chunk_appendf(&trash, "  runtime uid: %d\n", geteuid());
        chunk_appendf(&trash, "  boot gid: %d\n", post_mortem.process.boot_gid);
+       chunk_appendf(&trash, "  runtime gid: %d\n", getegid());
 
        if ((ulong)post_mortem.process.limit_fd.rlim_cur != RLIM_INFINITY)
                chunk_appendf(&trash, "  fd limit (soft): %lu\n", (ulong)post_mortem.process.limit_fd.rlim_cur);
@@ -2271,6 +2282,8 @@ static int feed_post_mortem()
        post_mortem.process.pid = getpid();
        post_mortem.process.boot_uid = geteuid();
        post_mortem.process.boot_gid = getegid();
+       post_mortem.process.argc = global.argc;
+       post_mortem.process.argv = global.argv;
 
        getrlimit(RLIMIT_NOFILE, &post_mortem.process.limit_fd);
        getrlimit(RLIMIT_DATA, &post_mortem.process.limit_ram);
index c987fdbfa771a664a3b3078313cc81ab05d4f5a7..afccf0912675a654780de72ce855f7719a1c5988 100644 (file)
@@ -1557,6 +1557,11 @@ static void init_early(int argc, char **argv)
        totalconn = actconn = listeners = stopping = 0;
        killed = pid = 0;
 
+       /* cast to one byte in order to fill better a 3 bytes hole in the global struct,
+        * we hopefully will never start with > than 255 args
+        */
+       global.argc = (unsigned char)argc;
+       global.argv = argv;
        global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
        global.rlimit_memmax_all = HAPROXY_MEMMAX;
        global.mode = MODE_STARTING;