Skip to content

Commit 7bbf156

Browse files
committed
Fix consume_stream full buffer scenario (stdout or stderr gets 16KB without any newlines).
1 parent a7dd38a commit 7bbf156

File tree

2 files changed

+46
-36
lines changed

2 files changed

+46
-36
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2009-2020 Michael Truog <mjtruog at protonmail dot com>
3+
Copyright (c) 2009-2023 Michael Truog <mjtruog at protonmail dot com>
44

55
Permission is hereby granted, free of charge, to any person obtaining a
66
copy of this software and associated documentation files (the "Software"),

port.cpp

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//
88
// MIT License
99
//
10-
// Copyright (c) 2009-2020 Michael Truog <mjtruog at protonmail dot com>
10+
// Copyright (c) 2009-2023 Michael Truog <mjtruog at protonmail dot com>
1111
//
1212
// Permission is hereby granted, free of charge, to any person obtaining a
1313
// copy of this software and associated documentation files (the "Software"),
@@ -810,37 +810,46 @@ int GEPD::consume_stream(int fd, short & revents,
810810
return GEPD::ExitStatus::poll_NVAL;
811811
revents = 0;
812812

813+
bool flush = false;
814+
size_t i_flush = 0;
813815
ssize_t left = stream.size() - i;
814-
ssize_t readBytes;
815-
while ((readBytes = read(fd, &stream[i], left)) == left &&
816-
stream.grow())
816+
if (left == 0)
817817
{
818-
i += left;
819-
left = stream.size() - i;
820-
bool ready = true;
821-
data_ready(fd, ready);
822-
if (ready == false)
823-
break;
818+
// stream is full, flush it
819+
flush = true;
820+
i_flush = i - 1;
824821
}
825-
if (readBytes == 0 && i == 0)
826-
return GEPD::ExitStatus::success;
827-
else if (readBytes == -1)
828-
return errno_read();
829-
i += readBytes; // i is the next index to read at, always
830-
831-
// only send stderr output before the last newline character
832-
bool foundNewline = false;
833-
size_t iNewline = 0;
834-
for (ssize_t j = i - 1; ! foundNewline && j >= 0; --j)
822+
else
835823
{
836-
if (stream[j] == '\n')
824+
ssize_t read_bytes;
825+
while ((read_bytes = read(fd, &stream[i], left)) == left &&
826+
stream.grow())
827+
{
828+
i += left;
829+
left = stream.size() - i;
830+
bool ready = true;
831+
data_ready(fd, ready);
832+
if (ready == false)
833+
break;
834+
}
835+
if (read_bytes == 0 && i == 0)
836+
return GEPD::ExitStatus::success;
837+
else if (read_bytes == -1)
838+
return errno_read();
839+
i += read_bytes; // i is the next index to read at, always
840+
841+
// send stdout/stderr output before the last newline character
842+
for (ssize_t j = i - 1; ! flush && j >= 0; --j)
837843
{
838-
foundNewline = true;
839-
iNewline = j;
844+
if (stream[j] == '\n')
845+
{
846+
flush = true;
847+
i_flush = j;
848+
}
840849
}
841850
}
842851

843-
if (foundNewline)
852+
if (flush)
844853
{
845854
int index = sizeof(OUTPUT_PREFIX_TYPE);
846855
if (ei_encode_version(send_buffer.get<char>(), &index))
@@ -851,25 +860,25 @@ int GEPD::consume_stream(int fd, short & revents,
851860
return GEPD::ExitStatus::ei_encode_error;
852861
if (ei_encode_ulong(send_buffer.get<char>(), &index, pid))
853862
return GEPD::ExitStatus::ei_encode_error;
854-
if (send_buffer.reserve(index + (iNewline + 1) + 1) == false)
863+
if (send_buffer.reserve(index + (i_flush + 1) + 1) == false)
855864
return GEPD::ExitStatus::write_overflow;
856865
if (ei_encode_string_len(send_buffer.get<char>(), &index,
857-
stream.get<char>(), iNewline + 1))
866+
stream.get<char>(), i_flush + 1))
858867
return GEPD::ExitStatus::ei_encode_error;
859868
int status;
860869
if ((status = write_cmd(send_buffer, index -
861870
sizeof(OUTPUT_PREFIX_TYPE))))
862871
return status;
863872
// keep any data not yet sent (waiting for a newline)
864-
if (iNewline == i - 1)
873+
if (i_flush == i - 1)
865874
{
866875
i = 0;
867876
}
868877
else
869878
{
870-
size_t const remainingBytes = i - iNewline - 1;
871-
stream.move(iNewline + 1, remainingBytes, 0);
872-
i = remainingBytes;
879+
size_t const remaining_bytes = i - i_flush - 1;
880+
stream.move(i_flush + 1, remaining_bytes, 0);
881+
i = remaining_bytes;
873882
}
874883
}
875884
return GEPD::ExitStatus::success;
@@ -884,8 +893,9 @@ int GEPD::flush_stream(int fd, short revents,
884893
return GEPD::ExitStatus::success;
885894

886895
ssize_t left = stream.size() - i;
887-
ssize_t readBytes;
888-
while ((readBytes = read(fd, &stream[i], left)) == left &&
896+
assert(left > 0);
897+
ssize_t read_bytes;
898+
while ((read_bytes = read(fd, &stream[i], left)) == left &&
889899
stream.grow())
890900
{
891901
i += left;
@@ -895,10 +905,10 @@ int GEPD::flush_stream(int fd, short revents,
895905
if (ready == false)
896906
break;
897907
}
898-
if (readBytes == 0 && i == 0)
908+
if (read_bytes == 0 && i == 0)
899909
return GEPD::ExitStatus::success;
900-
else if (readBytes != -1)
901-
i += readBytes; // i is the next index to read at, always
910+
else if (read_bytes != -1)
911+
i += read_bytes; // i is the next index to read at, always
902912

903913
size_t const total = i - 1;
904914
i = 0;

0 commit comments

Comments
 (0)