Repository: Rapptz/discord.py
File: discord/player.py (Python)

Code before:
                    self._stdin.close()
                return
            try:
                if self._stdin is not None:
                    self._stdin.write(data)
            except Exception:
                _log.debug('Write error for %s, this is probably not a problem', self, exc_info=True)
                # at this point the source data is either exhausted or the process is fubar
                self._process.terminate()
                return

    def _pipe_reader(self, dest: IO[bytes]) -> None:
        while self._process:
            if self._stderr is None:
                return
            try:
                data: bytes = self._stderr.read(self.BLOCKSIZE)
            except Exception:
                _log.debug('Read error for %s, this is probably not a problem', self, exc_info=True)
                return
            if data is None:
                return
            # TODO: Do I need to check if this explodes?  catch OSError or something?
            #       What happens if dest can no longer be written to?  Keep reading without writing or exit?
            #       Does it pose an issue if the stderr pipe doesn't get read from?
            dest.write(data)

    def cleanup(self) -> None:
        self._kill_process()
        self._process = self._stdout = self._stdin = self._stderr = MISSING


class FFmpegPCMAudio(FFmpegAudio):
    """An audio source from FFmpeg (or AVConv).

    This launches a sub-process to a specific input file given.

    .. warning::

        You must have the ffmpeg or avconv executable in your path environment
        variable in order for this to work.

    Parameters
    ------------
    source: Union[:class:`str`, :class:`io.BufferedIOBase`]
        The input that ffmpeg will take and convert to PCM bytes.
        If ``pipe`` is ``True`` then this is a file-like object that is
        passed to the stdin of ffmpeg.
    executable: :class:`str`
        The executable name (and path) to use. Defaults to ``ffmpeg``.
    pipe: :class:`bool`

Review comment (refactor):
If an exception happens here then it should ideally properly clean up. It's probably as simple as just doing a `return` like you did elsewhere rather than propagating it to the thread exit.

Code after:
                    self._stdin.close()
                return
            try:
                if self._stdin is not None:
                    self._stdin.write(data)
            except Exception:
                _log.debug('Write error for %s, this is probably not a problem', self, exc_info=True)
                # at this point the source data is either exhausted or the process is fubar
                self._process.terminate()
                return

    def _pipe_reader(self, dest: IO[bytes]) -> None:
        while self._process:
            if self._stderr is None:
                return
            try:
                data: bytes = self._stderr.read(self.BLOCKSIZE)
            except Exception:
                _log.debug('Read error for %s, this is probably not a problem', self, exc_info=True)
                return
            if data is None:
                return
            try:
                dest.write(data)
            except Exception:
                _log.exception('Write error for %s', self)
                self._stderr.close()
                return

    def cleanup(self) -> None:
        self._kill_process()
        self._process = self._stdout = self._stdin = self._stderr = MISSING


class FFmpegPCMAudio(FFmpegAudio):
    """An audio source from FFmpeg (or AVConv).

    This launches a sub-process to a specific input file given.

    .. warning::

        You must have the ffmpeg or avconv executable in your path environment
        variable in order for this to work.

    Parameters
    ------------
    source: Union[:class:`str`, :class:`io.BufferedIOBase`]
        The input that ffmpeg will take and convert to PCM bytes.
        If ``pipe`` is ``True`` then this is a file-like object that is
        passed to the stdin of ffmpeg.
    executable: :class:`str`