casaroli opened a new pull request, #3962: URL: https://github.com/apache/nuttx-apps/pull/3962
## Summary `gdbstub -p <port>` serves gdb over TCP. When a client closes the connection without a `k` packet, gdbstub does not serve another client: - `read()` returns 0 when the peer closed, and `gdb_recv()` called it again forever without blocking. gdbstub kept the CPU busy and never accepted the next client. gdb closes the connection this way on `disconnect`, or when gdb is killed. (gdb sends `k` first only when it exits normally; the stub already handles `k`.) - An error other than `ECONNRESET` from `gdb_process()` ended gdbstub. - A write to the closed socket can raise `SIGPIPE` (apache/nuttx#21324), which ends gdbstub when `CONFIG_SIG_SIGPIPE_ACTION` is enabled. - Each new client allocated a new gdb state (with the `CONFIG_LIB_GDBSTUB_PKTSIZE` packet buffer, 32 KiB by default); the old state leaked. This PR makes `gdb_recv()` return `-ECONNRESET` at end of file, as the stub does for `k`. In TCP mode, any error from `gdb_process()` ends the session: gdbstub frees the state, closes the connection and accepts the next client. The TCP mode sends with `send(..., MSG_NOSIGNAL)`. The tty mode (`-d <device>`) does not change. libs/libc/gdbstub needs no change: `gdb_process()` already returns the error of the receive function. ## Impact Only system/gdbstub in TCP mode. No change in the tty mode and no change in libs/libc/gdbstub. No documentation change: Documentation/applications/system/gdbstub has only a title. ## Testing qemu-armv8a:nsh (flat build, QEMU with HVF) on nuttx master 2eeaf9b6a33, with `CONFIG_NET_TCP`, `NET_LOOPBACK`, virtio-net (QEMU user network, host port forwarded to the guest port 1234), `LIB_GDBSTUB`, `SYSTEM_GDBSTUB`, `BOARD_MEMORY_RANGE` as in qemu-armv8a:gdbstub, `SIG_DEFAULT` and `SIG_SIGPIPE_ACTION`. `gdbstub -p 1234 &` runs, then: - close: a test program (builtin app) in the guest sends `?`, reads the reply, acks it and closes the socket. A second client then sends `?`. - reset: the first client sends `g` and closes the socket without reading the reply (the close sends a reset). A second client then sends `?`. - reset during a reply: the first client sends `?`, does not read the reply, sends `g` and closes at once, so that gdbstub writes to the reset connection. This case also runs with a test-only nuttx patch (not part of any PR) that makes the TCP send return `EPIPE` instead of `ENOTCONN` after a reset, as POSIX gives it, so that the write raises `SIGPIPE`. - gdb: aarch64-none-elf-gdb (Arm GNU Toolchain 14.2) on the host connects, runs `info threads` and `disconnect`, two times. | Case | apps master b017038e5 | this PR | |---|---|---| | close: second client | no reply (`EAGAIN` after 5 s), gdbstub stays Ready: FAIL | PASS | | reset: second client | no reply, gdbstub stays Ready: FAIL | PASS | | gdb: first session | lists 6 threads | lists 6 threads | | gdb: second session | gdb times out, no reply: FAIL | PASS (6 threads) | | reset during a reply: second client | no reply, gdbstub stays Ready: FAIL | PASS | | reset during a reply, TCP `EPIPE`: second client | `ECONNREFUSED`, gdbstub ended (by `SIGPIPE`: without the patch it stays): FAIL | PASS | | ostest after the cases | does not end in 400 s while gdbstub spins (0 after the `SIGPIPE` case, gdbstub is gone) | 0 | The close and reset cases also pass on this PR with the TCP `EPIPE` patch. Builds with `EXTRAFLAGS="-Wno-cpp -Werror"`, no compiler warnings: esp32c3-legacy-devkit:gdbstub; qemu-armv8a:gdbstub and qemu-armv7a:gdbstub with `CONFIG_SYSTEM_GDBSTUB` (tty mode, no network); qemu-armv8a:nsh, rv-virt:nsh64 and qemu-armv7a:nsh with `CONFIG_NET_TCP`, `LIB_GDBSTUB` and `SYSTEM_GDBSTUB`. `tools/checkpatch.sh -c -u -m -g` passes. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
