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:
parent
e8099f01b5
commit
73013a3c04
2
NEWS
2
NEWS
|
@ -2,7 +2,7 @@ ver 0.20.19 (not yet released)
|
||||||
* protocol
|
* protocol
|
||||||
- validate absolute seek time, reject negative values
|
- validate absolute seek time, reject negative values
|
||||||
* input
|
* input
|
||||||
- mms: fix lockup bug
|
- mms: fix lockup bug and a crash bug
|
||||||
* macOS: fix crash bug
|
* macOS: fix crash bug
|
||||||
|
|
||||||
ver 0.20.18 (2018/02/24)
|
ver 0.20.18 (2018/02/24)
|
||||||
|
|
|
@ -26,8 +26,12 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
ThreadInputStream::~ThreadInputStream()
|
void
|
||||||
|
ThreadInputStream::Stop() noexcept
|
||||||
{
|
{
|
||||||
|
if (!thread.IsDefined())
|
||||||
|
return;
|
||||||
|
|
||||||
{
|
{
|
||||||
const std::lock_guard<Mutex> lock(mutex);
|
const std::lock_guard<Mutex> lock(mutex);
|
||||||
close = true;
|
close = true;
|
||||||
|
@ -42,6 +46,7 @@ ThreadInputStream::~ThreadInputStream()
|
||||||
buffer->Clear();
|
buffer->Clear();
|
||||||
HugeFree(buffer->Write().data, buffer_size);
|
HugeFree(buffer->Write().data, buffer_size);
|
||||||
delete buffer;
|
delete buffer;
|
||||||
|
buffer = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
template<typename T> class CircularBuffer;
|
template<typename T> class CircularBuffer;
|
||||||
|
@ -39,6 +40,11 @@ template<typename T> class CircularBuffer;
|
||||||
* manages the thread and the buffer.
|
* manages the thread and the buffer.
|
||||||
*
|
*
|
||||||
* This works only for "streams": unknown length, no seeking, no tags.
|
* 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 {
|
class ThreadInputStream : public InputStream {
|
||||||
const char *const plugin;
|
const char *const plugin;
|
||||||
|
@ -76,7 +82,13 @@ public:
|
||||||
thread(BIND_THIS_METHOD(ThreadFunc)),
|
thread(BIND_THIS_METHOD(ThreadFunc)),
|
||||||
buffer_size(_buffer_size) {}
|
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.
|
* Initialize the object and start the thread.
|
||||||
|
@ -90,6 +102,12 @@ public:
|
||||||
size_t Read(void *ptr, size_t size) override final;
|
size_t Read(void *ptr, size_t size) override final;
|
||||||
|
|
||||||
protected:
|
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) {
|
void SetMimeType(const char *_mime) {
|
||||||
assert(thread.IsInside());
|
assert(thread.IsInside());
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,10 @@ public:
|
||||||
MMS_BUFFER_SIZE) {
|
MMS_BUFFER_SIZE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~MmsInputStream() noexcept override {
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Open() override;
|
virtual void Open() override;
|
||||||
virtual size_t ThreadRead(void *ptr, size_t size) override;
|
virtual size_t ThreadRead(void *ptr, size_t size) override;
|
||||||
|
|
Loading…
Reference in New Issue