)]}'
{
  "commit": "dca18cb6a100fa87d6478a465e48ddc1d9ed943a",
  "tree": "5081c914c2700efdb4e917668e95dc13feacdacc",
  "parents": [
    "bee9d0068824629a136afc02818a1495209186ae"
  ],
  "author": {
    "name": "Tom de Vries",
    "email": "tdevries@suse.de",
    "time": "Mon Sep 23 09:53:54 2024 +0200"
  },
  "committer": {
    "name": "Tom de Vries",
    "email": "tdevries@suse.de",
    "time": "Mon Sep 23 09:53:54 2024 +0200"
  },
  "message": "[gdb/testsuite] Fix failure in gdb.threads/signal-sigtrap.exp\n\nThe test-case gdb.threads/signal-sigtrap.exp:\n- installs a signal handler called sigtrap_handler for SIGTRAP,\n- sets a breakpoint on sigtrap_handler, and\n- expects the breakpoint to trigger after issuing \"signal SIGTRAP\".\n\nUsually, that happens indeed:\n...\n(gdb) signal SIGTRAP^M\nContinuing with signal SIGTRAP.^M\n^M\nThread 1 \"signal-sigtrap\" hit Breakpoint 2, sigtrap_handler (sig\u003d5)^M\n28      }^M\n(gdb) PASS: $exp: sigtrap thread 1: signal SIGTRAP reaches handler\n...\n\nOccasionally, I run into this failure on openSUSE Tumbleweed:\n...\n(gdb) signal SIGTRAP^M\nContinuing with signal SIGTRAP.^M\n^M\nThread 1 \"signal-sigtrap\" received signal SIGTRAP, Trace/breakpoint trap.^M\n__pthread_create_2_1 () at pthread_create.c:843^M\n(gdb) FAIL: $exp: sigtrap thread 1: signal SIGTRAP reaches handler\n...\n\nAFAIU, the problem is in the situation that is setup before issuing that\ncommand, by running to a breakpoint in thread_function:\n...\nvoid *thread_function (void *arg) {\n  return NULL;\n}\nint main (void) {\n  pthread_t child_thread;\n  signal (SIGTRAP, sigtrap_handler);\n  pthread_create (\u0026child_thread, NULL, thread_function, NULL);\n  pthread_join (child_thread, NULL);\n  return 0;\n}\n...\n\nIn the passing case, thread 2 is stopped in thread_function, and thread 1 is\nstopped somewhere in pthread_join:\n...\n(gdb) info threads^M\n  Id   Target Id                                          Frame ^M\n  1    Thread ... (LWP ...) \"signal-sigtrap\" __futex_abstimed_wait_common64 ()\n* 2    Thread ... (LWP ...) \"signal-sigtrap\" thread_function ()\n...\n\nIn the failing case, thread 2 is stopped in thread_function, but thread 1 is\nstopped somewhere in pthread_create:\n...\n(gdb) info threads^M\n  Id   Target Id                                          Frame ^M\n  1    Thread ... (LWP ...) \"signal-sigtrap\" __GI___clone3 ()\n* 2    Thread ... (LWP ...) \"signal-sigtrap\" thread_function ()\n...\n\nWhat I think happens is that pthread_create blocks SIGTRAP at some point, and\nif the \"signal SIGTRAP\" command is issued while that is the case, the signal\nbecomes pending and consequently there\u0027s no longer a guarantee that the signal\nwill be delivered to the inferior.\n\nInstead the signal will be handled by gdb like this:\n...\n(gdb) info signals SIGTRAP\nSignal        Stop\tPrint\tPass to program\tDescription\nSIGTRAP       Yes\tYes\tNo\t\tTrace/breakpoint trap\n...\n\nFix this by adding a barrier that ensures that pthread_create is done before\nwe issue the \"signal SIGTRAP\" command.\n\nLikewise in test-case gdb.threads/signal-command-handle-nopass.exp.\n\nUsing the fixed test-case, I tested my theory by explicitly blocking SIGTRAP:\n...\n+  sigset_t old_ss, new_ss;\n+  sigemptyset (\u0026new_ss);\n+  sigaddset (\u0026new_ss, SIGTRAP);\n+  sigprocmask (SIG_BLOCK, \u0026new_ss, \u0026old_ss);\n+\n   /* Make sure that pthread_create is done once the breakpoint on\n      thread_function triggers.  */\n   pthread_barrier_wait (\u0026barrier);\n\n   pthread_join (child_thread, NULL);\n+  sigprocmask (SIG_SETMASK, \u0026old_ss, NULL);\n...\nand managed to reproduce the same failure:\n...\n(gdb) signal SIGTRAP^M\nContinuing with signal SIGTRAP.^M\n[Thread 0x7ffff7c00700 (LWP 13254) exited]^M\n^M\nThread 1 \"signal-sigtrap\" received signal SIGTRAP, Trace/breakpoint trap.^M\n0x00007ffff7c80056 in __GI___sigprocmask () sigprocmask.c:39^M\n(gdb) FAIL: $exp: sigtrap thread 1: signal SIGTRAP reaches handler\n...\n\nTested on x86_64-linux.\n\nPR testsuite/26867\nBug: https://sourceware.org/bugzilla/show_bug.cgi?id\u003d26867\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "6d82bd6f2568bf6613cb691d46184e446ecaba78",
      "old_mode": 33188,
      "old_path": "gdb/testsuite/gdb.threads/signal-command-handle-nopass.c",
      "new_id": "548d0d3701d6bf80f32fe9931f65e22fe5866769",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.threads/signal-command-handle-nopass.c"
    },
    {
      "type": "modify",
      "old_id": "24625ba9bacfc7af86fc64a61499dfc366bf809f",
      "old_mode": 33188,
      "old_path": "gdb/testsuite/gdb.threads/signal-sigtrap.c",
      "new_id": "7c903a13cf1f112f1af3f461397e5f5689605612",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.threads/signal-sigtrap.c"
    }
  ]
}
