@@ -883,9 +883,10 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len
if (err)
goto done;
- if (fd >= 0)
- err = write_packetized_from_fd(fd, process->in);
- else
+ if (fd >= 0) {
+ struct packet_scratch_space scratch;
+ err = write_packetized_from_fd(fd, process->in, &scratch);
+ } else
err = write_packetized_from_buf(src, len, process->in);
if (err)
goto done;
@@ -196,17 +196,25 @@ int packet_write_fmt_gently(int fd, const char *fmt, ...)
static int packet_write_gently(const int fd_out, const char *buf, size_t size)
{
- static char packet_write_buffer[LARGE_PACKET_MAX];
+ char header[4];
size_t packet_size;
- if (size > sizeof(packet_write_buffer) - 4)
+ if (size > LARGE_PACKET_DATA_MAX)
return error(_("packet write failed - data exceeds max packet size"));
packet_trace(buf, size, 1);
packet_size = size + 4;
- set_packet_header(packet_write_buffer, packet_size);
- memcpy(packet_write_buffer + 4, buf, size);
- if (write_in_full(fd_out, packet_write_buffer, packet_size) < 0)
+
+ set_packet_header(header, packet_size);
+
+ /*
+ * Write the header and the buffer in 2 parts so that we do not need
+ * to allocate a buffer or rely on a static buffer. This avoids perf
+ * and multi-threading issues.
+ */
+
+ if (write_in_full(fd_out, header, 4) < 0 ||
+ write_in_full(fd_out, buf, size) < 0)
return error(_("packet write failed"));
return 0;
}
@@ -242,19 +250,21 @@ void packet_buf_write_len(struct strbuf *buf, const char *data, size_t len)
packet_trace(data, len, 1);
}
-int write_packetized_from_fd(int fd_in, int fd_out)
+int write_packetized_from_fd(int fd_in, int fd_out,
+ struct packet_scratch_space *scratch)
{
- static char buf[LARGE_PACKET_DATA_MAX];
int err = 0;
ssize_t bytes_to_write;
while (!err) {
- bytes_to_write = xread(fd_in, buf, sizeof(buf));
+ bytes_to_write = xread(fd_in, scratch->buffer,
+ sizeof(scratch->buffer));
if (bytes_to_write < 0)
return COPY_READ_ERROR;
if (bytes_to_write == 0)
break;
- err = packet_write_gently(fd_out, buf, bytes_to_write);
+ err = packet_write_gently(fd_out, scratch->buffer,
+ bytes_to_write);
}
if (!err)
err = packet_flush_gently(fd_out);
@@ -5,6 +5,13 @@
#include "strbuf.h"
#include "sideband.h"
+#define LARGE_PACKET_MAX 65520
+#define LARGE_PACKET_DATA_MAX (LARGE_PACKET_MAX - 4)
+
+struct packet_scratch_space {
+ char buffer[LARGE_PACKET_DATA_MAX]; /* does not include header bytes */
+};
+
/*
* Write a packetized stream, where each line is preceded by
* its length (including the header) as a 4-byte hex number.
@@ -32,7 +39,7 @@ void packet_buf_write(struct strbuf *buf, const char *fmt, ...) __attribute__((f
void packet_buf_write_len(struct strbuf *buf, const char *data, size_t len);
int packet_flush_gently(int fd);
int packet_write_fmt_gently(int fd, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
-int write_packetized_from_fd(int fd_in, int fd_out);
+int write_packetized_from_fd(int fd_in, int fd_out, struct packet_scratch_space *scratch);
int write_packetized_from_buf(const char *src_in, size_t len, int fd_out);
/*
@@ -213,8 +220,7 @@ enum packet_read_status packet_reader_read(struct packet_reader *reader);
enum packet_read_status packet_reader_peek(struct packet_reader *reader);
#define DEFAULT_PACKET_MAX 1000
-#define LARGE_PACKET_MAX 65520
-#define LARGE_PACKET_DATA_MAX (LARGE_PACKET_MAX - 4)
+
extern char packet_buffer[LARGE_PACKET_MAX];
struct packet_writer {