input/thread: move code to Stop()

Fixes crash due to "pure virtual method called" in the "mms" input
plugin.  Closes #253
This commit is contained in:
Max Kellermann 2018-03-15 19:23:31 +01:00
parent e8099f01b5
commit 73013a3c04
4 changed files with 30 additions and 3 deletions

2
NEWS
View File

@ -2,7 +2,7 @@ ver 0.20.19 (not yet released)
* protocol
- validate absolute seek time, reject negative values
* input
- mms: fix lockup bug
- mms: fix lockup bug and a crash bug
* macOS: fix crash bug
ver 0.20.18 (2018/02/24)

View File

@ -26,8 +26,12 @@
#include <assert.h>
#include <string.h>
ThreadInputStream::~ThreadInputStream()
void
ThreadInputStream::Stop() noexcept
{
if (!thread.IsDefined())
return;
{
const std::lock_guard<Mutex> lock(mutex);
close = true;
@ -42,6 +46,7 @@ ThreadInputStream::~ThreadInputStream()
buffer->Clear();
HugeFree(buffer->Write().data, buffer_size);
delete buffer;
buffer = nullptr;
}
}

View File

@ -27,6 +27,7 @@
#include <exception>
#include <assert.h>
#include <stdint.h>
template<typename T> class CircularBuffer;
@ -39,6 +40,11 @@ template<typename T> class CircularBuffer;
* manages the thread and the buffer.
*
* This works only for "streams": unknown length, no seeking, no tags.
*
* The implementation must call Stop() before its destruction
* completes. This cannot be done in ~ThreadInputStream() because at
* this point, the class has been morphed back to #ThreadInputStream
* and the still-running thread will crash due to pure method call.
*/
class ThreadInputStream : public InputStream {
const char *const plugin;
@ -76,7 +82,13 @@ public:
thread(BIND_THIS_METHOD(ThreadFunc)),
buffer_size(_buffer_size) {}
virtual ~ThreadInputStream();
#ifndef NDEBUG
~ThreadInputStream() override {
/* Stop() must have been called already */
assert(!thread.IsDefined());
assert(buffer == nullptr);
}
#endif
/**
* Initialize the object and start the thread.
@ -90,6 +102,12 @@ public:
size_t Read(void *ptr, size_t size) override final;
protected:
/**
* Stop the thread and free the buffer. This must be called
* before destruction of this object completes.
*/
void Stop() noexcept;
void SetMimeType(const char *_mime) {
assert(thread.IsInside());

View File

@ -39,6 +39,10 @@ public:
MMS_BUFFER_SIZE) {
}
~MmsInputStream() noexcept override {
Stop();
}
protected:
virtual void Open() override;
virtual size_t ThreadRead(void *ptr, size_t size) override;