diff --git a/NEWS b/NEWS index c0512ac8a..73fcfa4e7 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.21.9 (not yet released) +* input + - buffer: fix deadlock bug * Android - fix crash on ARMv7 - request storage permission on Android 6+ 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 @@ -164,6 +164,30 @@ BufferedInputStream::RunThread() noexcept idle = false; 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();