summaryrefslogtreecommitdiff
path: root/src/input
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2019-05-16 21:01:26 +0200
committerMax Kellermann <max@musicpd.org>2019-05-16 21:11:03 +0200
commitca06d9d3bf448066c8bb1795ae9a780a18036659 (patch)
treeb6d88797567f04460cb74c4cc758f159d067804e /src/input
parented2db04f4350715a8535a1cb734015e7d9acdd48 (diff)
input/buffered: fix deadlock bug
Diffstat (limited to 'src/input')
-rw-r--r--src/input/BufferedInputStream.cxx24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/input/BufferedInputStream.cxx b/src/input/BufferedInputStream.cxx
index a5688de47..7ac4f0a2c 100644
--- a/src/input/BufferedInputStream.cxx
+++ b/src/input/BufferedInputStream.cxx
@@ -165,6 +165,30 @@ BufferedInputStream::RunThread() noexcept
seek = false;
client_cond.signal();
} else if (!idle && !read_error &&
+ offset != input->GetOffset() &&
+ !IsAvailable()) {
+ /* a past Seek() call was a no-op because data
+ was already available at that position, but
+ now we've reached a new position where
+ there is no more data in the buffer, and
+ our input is reading somewhere else (maybe
+ stuck at the end of the file); to find a
+ way out, we now seek our input to our
+ reading position to be able to fill our
+ buffer */
+
+ try {
+ input->Seek(offset);
+ } catch (...) {
+ /* this is really a seek error, but we
+ register it as a read_error,
+ because seek_error is only checked
+ by Seek(), and at our frontend (our
+ own InputStream interface) is in
+ "read" mode */
+ read_error = std::current_exception();
+ }
+ } else if (!idle && !read_error &&
input->IsAvailable() && !input->IsEOF()) {
const auto read_offset = input->GetOffset();
auto w = buffer.Write(read_offset);