)]}'
{
  "commit": "b1c0ab20809a502b2d2224fecb0dca3ada2e9b22",
  "tree": "5bf5fd6db3c2f95f8e94b09edd2c4adc68cfff01",
  "parents": [
    "f559e52a8e79585e0b13156e949a7fd46060a714"
  ],
  "author": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Wed Jul 12 21:56:50 2023 +0100"
  },
  "committer": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Thu Aug 03 14:55:31 2023 +0100"
  },
  "message": "gdb: avoid double stop after failed breakpoint condition check\n\nThis commit replaces this earlier commit:\n\n  commit 2e411b8c68eb2b035b31d5b00d940d4be1a0928b\n  Date:   Fri Oct 14 14:53:15 2022 +0100\n\n      gdb: don\u0027t always print breakpoint location after failed condition check\n\nand is a result of feedback received here[1].\n\nThe original commit addressed a problem where, if a breakpoint\ncondition included an inferior function call, and if the inferior\nfunction call failed, then GDB would announce the stop twice.  Here\u0027s\nan example of GDB\u0027s output before the above commit that shows the\nproblem being addressed:\n\n  (gdb) break foo if (some_func ())\n  Breakpoint 1 at 0x40111e: file bpcond.c, line 11.\n  (gdb) r\n  Starting program: /tmp/bpcond\n\n  Program received signal SIGSEGV, Segmentation fault.\n  0x0000000000401116 in some_func () at bpcond.c:5\n  5       return *p;\n  Error in testing condition for breakpoint 1:\n  The program being debugged stopped while in a function called from GDB.\n  Evaluation of the expression containing the function\n  (some_func) will be abandoned.\n  When the function is done executing, GDB will silently stop.\n\n  Breakpoint 1, 0x0000000000401116 in some_func () at bpcond.c:5\n  5       return *p;\n  (gdb)\n\nThe original commit addressed this issue in breakpoint.c, by spotting\nthat the $pc had changed while evaluating the breakpoint condition,\nand inferring from this that GDB must have stopped elsewhere.\n\nHowever, the way in which the original commit suppressed the second\nstop announcement was to set bpstat::print to true -- this tells GDB\nnot to print the frame during the stop announcement, and for the CLI\nthis is fine, however, it was pointed out that for the MI this still\nisn\u0027t really enough.  Below is an example from an MI session after the\nabove commit was applied, this shows the problem with the above\ncommit:\n\n  -break-insert -c \"cond_fail()\" foo\n  ^done,bkpt\u003d{number\u003d\"1\",type\u003d\"breakpoint\",disp\u003d\"keep\",enabled\u003d\"y\",addr\u003d\"0x000000000040111e\",func\u003d\"foo\",file\u003d\"/tmp/mi-condbreak-fail.c\",line\u003d\"30\",thread-groups\u003d[\"i1\"],cond\u003d\"cond_fail()\",times\u003d\"0\",original-location\u003d\"foo\"}\n  (gdb)\n  -exec-run\n  \u003dthread-group-started,id\u003d\"i1\",pid\u003d\"2636270\"\n  \u003dthread-created,id\u003d\"1\",group-id\u003d\"i1\"\n  \u003dlibrary-loaded,id\u003d\"/lib64/ld-linux-x86-64.so.2\",target-name\u003d\"/lib64/ld-linux-x86-64.so.2\",host-name\u003d\"/lib64/ld-linux-x86-64.so.2\",symbols-loaded\u003d\"0\",thread-group\u003d\"i1\",ranges\u003d[{from\u003d\"0x00007ffff7fd3110\",to\u003d\"0x00007ffff7ff2bb4\"}]\n  ^running\n  *running,thread-id\u003d\"all\"\n  (gdb)\n  \u003dlibrary-loaded,id\u003d\"/lib64/libm.so.6\",target-name\u003d\"/lib64/libm.so.6\",host-name\u003d\"/lib64/libm.so.6\",symbols-loaded\u003d\"0\",thread-group\u003d\"i1\",ranges\u003d[{from\u003d\"0x00007ffff7e59390\",to\u003d\"0x00007ffff7ef4f98\"}]\n  \u003dlibrary-loaded,id\u003d\"/lib64/libc.so.6\",target-name\u003d\"/lib64/libc.so.6\",host-name\u003d\"/lib64/libc.so.6\",symbols-loaded\u003d\"0\",thread-group\u003d\"i1\",ranges\u003d[{from\u003d\"0x00007ffff7ca66b0\",to\u003d\"0x00007ffff7df3c5f\"}]\n  ~\"\\nProgram\"\n  ~\" received signal SIGSEGV, Segmentation fault.\\n\"\n  ~\"0x0000000000401116 in cond_fail () at /tmp/mi-condbreak-fail.c:24\\n\"\n  ~\"24\\t  return *p;\\t\\t\\t/* Crash here.  */\\n\"\n  *stopped,reason\u003d\"signal-received\",signal-name\u003d\"SIGSEGV\",signal-meaning\u003d\"Segmentation fault\",frame\u003d{addr\u003d\"0x0000000000401116\",func\u003d\"cond_fail\",args\u003d[],file\u003d\"/tmp/mi-condbreak-fail.c\",fullname\u003d\"/tmp/mi-condbreak-fail.c\",line\u003d\"24\",arch\u003d\"i386:x86-64\"},thread-id\u003d\"1\",stopped-threads\u003d\"all\",core\u003d\"9\"\n  \u0026\"Error in testing condition for breakpoint 1:\\n\"\n  \u0026\"The program being debugged was signaled while in a function called from GDB.\\n\"\n  \u0026\"GDB remains in the frame where the signal was received.\\n\"\n  \u0026\"To change this behavior use \\\"set unwindonsignal on\\\".\\n\"\n  \u0026\"Evaluation of the expression containing the function\\n\"\n  \u0026\"(cond_fail) will be abandoned.\\n\"\n  \u0026\"When the function is done executing, GDB will silently stop.\\n\"\n  \u003dbreakpoint-modified,bkpt\u003d{number\u003d\"1\",type\u003d\"breakpoint\",disp\u003d\"keep\",enabled\u003d\"y\",addr\u003d\"0x000000000040111e\",func\u003d\"foo\",file\u003d\"/tmp/mi-condbreak-fail.c\",fullname\u003d\"/tmp/mi-condbreak-fail.c\",line\u003d\"30\",thread-groups\u003d[\"i1\"],cond\u003d\"cond_fail()\",times\u003d\"1\",original-location\u003d\"foo\"}\n  *stopped\n  (gdb)\n\nNotice that we still see two \u0027*stopped\u0027 lines, the first includes the\nfull frame information, while the second has no frame information,\nthis is a result of bpstat::print having been set.  Ideally, the\nsecond \u0027*stopped\u0027 line should not be present.\n\nBy setting bpstat::print I was addressing the problem too late, this\nflag really only changes how interp::on_normal_stop prints the stop\nevent, and interp::on_normal_stop is called (indirectly) from the\nnormal_stop function in infrun.c.  A better solution is to avoid\ncalling normal_stop at all for the stops which should not be reported\nto the user, and this is what I do in this commit.\n\nThis commit has 3 parts:\n\n  1. In breakpoint.c, revert the above commit,\n\n  2. In fetch_inferior_event (infrun.c), capture the stop-id before\n  calling handle_inferior_event.  If, after calling\n  handle_inferior_event, the stop-id has changed, then this indicates\n  that somewhere within handle_inferior_event, a stop was announced to\n  the user.  If this is the case then GDB should not call normal_stop,\n  and we should rely on whoever announced the stop to ensure that we\n  are in a PROMPT_NEEDED state, which means the prompt will be\n  displayed once fetch_inferior_event returns.  And,\n\n  3. In infcall.c, do two things:\n\n     (a) In run_inferior_call, after making the inferior call, ensure\n     that either async_disable_stdin or async_enable_stdin is called\n     to put the prompt state, and stdin handling into the correct\n     state based on whether the inferior call completed successfully\n     or not, and\n\n     (b) In call_thread_fsm::should_stop, call async_enable_stdin\n     rather than changing the prompt state directly.  This isn\u0027t\n     strictly necessary, but helped me understand this code more.\n     This async_enable_stdin call is only reached if normal_stop is\n     not going to be called, and replaces the async_enable_stdin call\n     that exists in normal_stop.  Though we could just adjust the\n     prompt state if felt (to me) much easier to understand when I\n     could see this call and the corresponding call in normal_stop.\n\nWith these changes in place now, when the inferior call (from the\nbreakpoint condition) fails, infcall.c leaves the prompt state as\nPROMPT_NEEDED, and leaves stdin registered with the event loop.\n\nBack in fetch_inferior_event GDB notices that the stop-id has changed\nand so avoids calling normal_stop.\n\nAnd on return from fetch_inferior_event GDB will display the prompt\nand handle input from stdin.\n\nAs normal_stop is not called the MI problem is solved, and the test\nadded in the earlier mentioned commit still passes just fine, so the\nCLI has not regressed.\n\n[1] https://inbox.sourceware.org/gdb-patches/6fd4aa13-6003-2563-5841-e80d5a55d59e@palves.net/\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "d898167b7e1bbdc722e8b57b786fc4c5ab47a9fb",
      "old_mode": 33188,
      "old_path": "gdb/breakpoint.c",
      "new_id": "93634bd7e51b307be199f87a31aba553975081cf",
      "new_mode": 33188,
      "new_path": "gdb/breakpoint.c"
    },
    {
      "type": "modify",
      "old_id": "ddf325a62a553bb301366733c47aa67f0948bded",
      "old_mode": 33188,
      "old_path": "gdb/infcall.c",
      "new_id": "bea5b185ddc2afd6c5a91550c5a2d61f6e1b757d",
      "new_mode": 33188,
      "new_path": "gdb/infcall.c"
    },
    {
      "type": "modify",
      "old_id": "7efa0617526c788fa01a2a21576710e477e9f065",
      "old_mode": 33188,
      "old_path": "gdb/infrun.c",
      "new_id": "8286026e6c643c5bf488199bae7bfafa8114051d",
      "new_mode": 33188,
      "new_path": "gdb/infrun.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "94bd2484934e1fab5af52f25f06c8291954720cc",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.mi/mi-condbreak-fail.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "34be4b907d3f25c8a745622b1f6fb0c50debaba2",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.mi/mi-condbreak-fail.exp"
    }
  ]
}
