]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
DEBUG: cli: add a new "debug dev deadlock" expert command
authorWilly Tarreau <w@1wt.eu>
Fri, 15 Jul 2022 06:25:03 +0000 (08:25 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 15 Jul 2022 17:41:26 +0000 (19:41 +0200)
This command will create the requested number of tasks competing on a
lock, resulting in triggering the watchdog and crashing the process.
This will help stress the watchdog and inspect the lock debugging parts.

src/debug.c

index 45e91e068f645eb5f8c40a47f3b03c9f7ac2892a..639f9375b2dd5707a77793aafc2ace8eef63bc27 100644 (file)
@@ -457,6 +457,36 @@ static int debug_parse_cli_close(char **args, char *payload, struct appctx *appc
        return 1;
 }
 
+/* this is meant to cause a deadlock when more than one task is running it or when run twice */
+static struct task *debug_run_cli_deadlock(struct task *task, void *ctx, unsigned int state)
+{
+       static HA_SPINLOCK_T lock __maybe_unused;
+
+       HA_SPIN_LOCK(OTHER_LOCK, &lock);
+       return NULL;
+}
+
+/* parse a "debug dev deadlock" command. It always returns 1. */
+static int debug_parse_cli_deadlock(char **args, char *payload, struct appctx *appctx, void *private)
+{
+       int tasks;
+
+       if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
+               return 1;
+
+       _HA_ATOMIC_INC(&debug_commands_issued);
+       for (tasks = atoi(args[3]); tasks > 0; tasks--) {
+               struct task *t = task_new_on(tasks % global.nbthread);
+               if (!t)
+                       continue;
+               t->process = debug_run_cli_deadlock;
+               t->context = NULL;
+               task_wakeup(t, TASK_WOKEN_INIT);
+       }
+
+       return 1;
+}
+
 /* parse a "debug dev delay" command. It always returns 1. */
 static int debug_parse_cli_delay(char **args, char *payload, struct appctx *appctx, void *private)
 {
@@ -1535,6 +1565,7 @@ static struct cli_kw_list cli_kws = {{ },{
        {{ "debug", "dev", "bug", NULL },      "debug dev bug                           : call BUG_ON() and crash",                 debug_parse_cli_bug,   NULL, NULL, NULL, ACCESS_EXPERT },
        {{ "debug", "dev", "check", NULL },    "debug dev check                         : call CHECK_IF() and possibly crash",      debug_parse_cli_check, NULL, NULL, NULL, ACCESS_EXPERT },
        {{ "debug", "dev", "close", NULL },    "debug dev close  <fd>                   : close this file descriptor",              debug_parse_cli_close, NULL, NULL, NULL, ACCESS_EXPERT },
+       {{ "debug", "dev", "deadlock", NULL }, "debug dev deadlock [nbtask]             : deadlock between this number of tasks",   debug_parse_cli_deadlock, NULL, NULL, NULL, ACCESS_EXPERT },
        {{ "debug", "dev", "delay", NULL },    "debug dev delay  [ms]                   : sleep this long",                         debug_parse_cli_delay, NULL, NULL, NULL, ACCESS_EXPERT },
 #if defined(DEBUG_DEV)
        {{ "debug", "dev", "exec",  NULL },    "debug dev exec   [cmd] ...              : show this command's output",              debug_parse_cli_exec,  NULL, NULL, NULL, ACCESS_EXPERT },