pkt-line: add PACKET_READ_GENTLE_ON_READ_ERROR option

Introduce PACKET_READ_GENTLE_ON_READ_ERROR option to help libify the packet readers. So far, the (possibly indirect) callers of `get_packet_data()` can ask that function to return an error instead of `die()`ing upon end-of-file. However, random read errors will still cause the process to die. So let's introduce an explicit option to tell the packet reader machinery to please be nice and only return an error on read errors. This change prepares pkt-line for use by long-running daemon processes. Such processes should be able to serve multiple concurrent clients and and survive random IO errors. If there is an error on one connection, a daemon should be able to drop that connection and continue serving existing and future connections. This ability will be used by a Git-aware "Builtin FSMonitor" feature in a later patch series. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Mar 15, 2021 at 21:08 UTC c4ba57939745641a3c7622096fddfc77cecf0d39
2 files changed +25 -5
pkt-line.c
+17 -2
@@ -306,8 +306,11 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,
306 *src_size -= ret;
307 } else {
308 ret = read_in_full(fd, dst, size);
309 - if (ret < 0)
309 + if (ret < 0) {
310 + if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
311 + return error_errno(_("read error"));
312 die_errno(_("read error"));
313 + }
314 }
315
316 /* And complain if we didn't get enough bytes to satisfy the read. */
@@ -315,6 +318,8 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,
318 if (options & PACKET_READ_GENTLE_ON_EOF)
319 return -1;
320
321 + if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
322 + return error(_("the remote end hung up unexpectedly"));
323 die(_("the remote end hung up unexpectedly"));
324 }
325
@@ -343,6 +348,9 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
348 len = packet_length(linelen);
349
350 if (len < 0) {
351 + if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
352 + return error(_("protocol error: bad line length "
353 + "character: %.4s"), linelen);
354 die(_("protocol error: bad line length character: %.4s"), linelen);
355 } else if (!len) {
356 packet_trace("0000", 4, 0);
@@ -357,12 +365,19 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
365 *pktlen = 0;
366 return PACKET_READ_RESPONSE_END;
367 } else if (len < 4) {
368 + if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
369 + return error(_("protocol error: bad line length %d"),
370 + len);
371 die(_("protocol error: bad line length %d"), len);
372 }
373
374 len -= 4;
364 - if ((unsigned)len >= size)
375 + if ((unsigned)len >= size) {
376 + if (options & PACKET_READ_GENTLE_ON_READ_ERROR)
377 + return error(_("protocol error: bad line length %d"),
378 + len);
379 die(_("protocol error: bad line length %d"), len);
380 + }
381
382 if (get_packet_data(fd, src_buffer, src_len, buffer, len, options) < 0) {
383 *pktlen = -1;
pkt-line.h
+8 -3
@@ -68,10 +68,15 @@ int write_packetized_from_buf_no_flush(const char *src_in, size_t len, int fd_ou
68 *
69 * If options contains PACKET_READ_DIE_ON_ERR_PACKET, it dies when it sees an
70 * ERR packet.
71 + *
72 + * If options contains PACKET_READ_GENTLE_ON_READ_ERROR, we will not die
73 + * on read errors, but instead return -1. However, we may still die on an
74 + * ERR packet (if requested).
75 */
72 -#define PACKET_READ_GENTLE_ON_EOF (1u<<0)
73 -#define PACKET_READ_CHOMP_NEWLINE (1u<<1)
74 -#define PACKET_READ_DIE_ON_ERR_PACKET (1u<<2)
76 +#define PACKET_READ_GENTLE_ON_EOF (1u<<0)
77 +#define PACKET_READ_CHOMP_NEWLINE (1u<<1)
78 +#define PACKET_READ_DIE_ON_ERR_PACKET (1u<<2)
79 +#define PACKET_READ_GENTLE_ON_READ_ERROR (1u<<3)
80 int packet_read(int fd, char **src_buffer, size_t *src_len, char
81 *buffer, unsigned size, int options);
82