Skip to content

Commit

Permalink
Prevent stderr pipe buffer overflow on long running radio streams (#1170
Browse files Browse the repository at this point in the history
)

* Fix buffer overflow in stderr reading

* Prevent pipe buffer overflooding
  • Loading branch information
marcelveldt authored Mar 24, 2024
1 parent 6e5f523 commit dc3d6c8
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions music_assistant/server/helpers/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ async def start(self) -> None:
stdin=stdin if self._enable_stdin else None,
stdout=stdout if self._enable_stdout else None,
stderr=asyncio.subprocess.PIPE if self._enable_stderr else None,
# setting the buffer limit is important to prevent exceeding the limit
# when reading lines from stderr (e.g. with long running ffmpeg process)
# https://stackoverflow.com/questions/55457370/how-to-avoid-valueerror-separator-is-not-found-and-chunk-exceed-the-limit
limit=1024 * 1024,
)
LOGGER.debug("Started %s with PID %s", self._name, self.proc.pid)

Expand Down Expand Up @@ -216,9 +220,17 @@ async def communicate(self, input_data: bytes | None = None) -> tuple[bytes, byt

async def iter_stderr(self) -> AsyncGenerator[bytes, None]:
"""Iterate lines from the stderr stream."""
async with self._stderr_locked:
async for line in self.proc.stderr:
yield line
while not self.closed:
try:
async with self._stderr_locked:
async for line in self.proc.stderr:
yield line
except ValueError as err:
# we're waiting for a line (separator found), but the line was too big
# NOTE: this consumes the line that was too big
if "chunk exceed the limit" in str(err):
continue
raise

async def _feed_stdin(self, custom_stdin: AsyncGenerator[bytes, None]) -> None:
"""Feed stdin with chunks from an AsyncGenerator."""
Expand Down

0 comments on commit dc3d6c8

Please sign in to comment.