Write entire buffer in gdbserver write_prim

We had a customer bug report which was eventually tracked down to
gdbserver not fully sending a target description to gdb.  (This
presented as a timeout on the gdb side.)

The customer was using the WINAPI code, which does this:

  # define write(fd, buf, len) send (fd, (char *) buf, len, 0)

In this setup, I think it's possible to have a partial write.
However, gdbserver does not account for this possibility, despite the
fact that write_prim documents this.

This patch attempts to fix the problem by always writing the full
buffer in write_prim.  In this case the customer fixed their bug in a
different way, so we haven't actually tested this in the wild.

v2: Return bool from write_prim.

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
This commit is contained in:
Tom Tromey
2025-10-16 08:58:38 -06:00
parent 9452b2fb46
commit cdb5949407

View File

@@ -598,17 +598,25 @@ read_ptid (const char *buf, const char **obuf)
return ptid_t (pid, tid);
}
/* Write COUNT bytes in BUF to the client.
The result is the number of bytes written or -1 if error.
This may return less than COUNT. */
/* Write COUNT bytes in BUF to the client. Returns true if all bytes
were written, false (with errno set) if not. */
static int
write_prim (const void *buf, int count)
static bool
write_prim (const char *buf, int count)
{
if (remote_connection_is_stdio ())
return write (fileno (stdout), buf, count);
else
return write (remote_desc, buf, count);
while (count > 0)
{
int written;
if (remote_connection_is_stdio ())
written = write (fileno (stdout), buf, count);
else
written = write (remote_desc, buf, count);
if (written < 0)
return false;
buf += written;
count -= written;
}
return true;
}
/* Read COUNT bytes from the client and store in BUF.
@@ -664,7 +672,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
do
{
if (write_prim (buf2, p - buf2) != p - buf2)
if (!write_prim (buf2, p - buf2))
{
perror ("putpkt(write)");
free (buf2);
@@ -980,7 +988,7 @@ getpkt (char *buf)
fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
(c1 << 4) + c2, csum, buf);
if (write_prim ("-", 1) != 1)
if (!write_prim ("-", 1))
return -1;
}
@@ -988,7 +996,7 @@ getpkt (char *buf)
{
remote_debug_printf ("getpkt (\"%s\"); [sending ack]", buf);
if (write_prim ("+", 1) != 1)
if (!write_prim ("+", 1))
return -1;
remote_debug_printf ("[sent ack]");