This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
The following commit(s) were added to refs/heads/master by this push:
new da90652be system/gdbstub: Serve the next client when a TCP client
closes.
da90652be is described below
commit da90652bea1521b90b047306530efbbd9d805cc2
Author: Marco Casaroli <[email protected]>
AuthorDate: Mon Nov 2 13:21:29 2026 +0100
system/gdbstub: Serve the next client when a TCP client closes.
With "gdbstub -p <port>", a client that closes the connection stopped
the server:
- read() returns 0 when the peer closed, and gdb_recv() called it again
forever without blocking. gdbstub kept the CPU busy and never
accepted another client. This happens on the gdb command
"disconnect" or when gdb is killed (gdb sends "k" first only when
it exits normally).
- An error other than ECONNRESET from gdb_process() ended gdbstub.
- A write to the closed socket can raise SIGPIPE, which ends gdbstub
when the default action of SIGPIPE terminates the task.
- Each new client allocated a new gdb state; the old one leaked.
gdb_recv() now returns -ECONNRESET at end of file, as the stub does on a
"k" packet. 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 does
not change.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
system/gdbstub/gdbstub.c | 56 ++++++++++++++++++++++++++++++++++++++----------
1 file changed, 45 insertions(+), 11 deletions(-)
diff --git a/system/gdbstub/gdbstub.c b/system/gdbstub/gdbstub.c
index 9085a0860..c495e5fe1 100644
--- a/system/gdbstub/gdbstub.c
+++ b/system/gdbstub/gdbstub.c
@@ -72,7 +72,7 @@ static int gdb_monitor(FAR struct gdb_state_s *state, FAR
const char *cmd)
#endif
}
-static ssize_t gdb_send(FAR void *priv, FAR const char *buf, size_t len)
+static ssize_t gdb_write(FAR void *priv, FAR const char *buf, size_t len)
{
int fd = *(FAR int *)priv;
size_t i = 0;
@@ -92,6 +92,28 @@ static ssize_t gdb_send(FAR void *priv, FAR const char *buf,
size_t len)
return len;
}
+#ifdef CONFIG_NET
+static ssize_t gdb_send(FAR void *priv, FAR const char *buf, size_t len)
+{
+ int fd = *(FAR int *)priv;
+ size_t i = 0;
+
+ while (i < len)
+ {
+ ssize_t ret = send(fd, buf + i, len - i, MSG_NOSIGNAL);
+
+ if (ret < 0)
+ {
+ return -errno;
+ }
+
+ i += ret;
+ }
+
+ return len;
+}
+#endif
+
static ssize_t gdb_recv(FAR void *priv, FAR void *buf,
size_t len)
{
@@ -106,6 +128,10 @@ static ssize_t gdb_recv(FAR void *priv, FAR void *buf,
{
return -errno;
}
+ else if (ret == 0)
+ {
+ return -ECONNRESET; /* The peer closed the connection */
+ }
i += ret;
}
@@ -215,7 +241,17 @@ reconnect:
usage(argv[0]);
}
- state = gdb_state_init(gdb_send, gdb_recv, gdb_monitor, &fd);
+#ifdef CONFIG_NET
+ if (port)
+ {
+ state = gdb_state_init(gdb_send, gdb_recv, gdb_monitor, &fd);
+ }
+ else
+#endif
+ {
+ state = gdb_state_init(gdb_write, gdb_recv, gdb_monitor, &fd);
+ }
+
if (state == NULL)
{
ret = -ENOMEM;
@@ -225,18 +261,16 @@ reconnect:
do
{
ret = gdb_process(state, 0, NULL);
- if (ret == -ECONNRESET)
- {
#ifdef CONFIG_NET
- if (port)
- {
- close(fd);
- goto reconnect;
- }
+ if (ret < 0 && port)
+ {
+ /* The session ended: wait for the next client */
-#endif
- continue;
+ gdb_state_uninit(state);
+ close(fd);
+ goto reconnect;
}
+#endif
}
while (ret >= 0);