currently there was a problem where thread was deleted within itself, so when
Thread::entrypoint was being finished, it used variabiles of the thread that
was already deleted, which is naturally problematic, since they could take any
value...
The problem is quite hard to understand (and was hard to debug), but is most
clearly illustrated by valgrind data on ChromaKey plugin:
==11903== Invalid read of size 4
==11903== at 0x46B4001: Thread::entrypoint(void*) (in
/usr/lib/libguicast.so.1.0.0)
==11903== by 0x4BDBE5F: start_thread (in
/lib/tls/i686/cmov/libpthread-2.3.6.so)
==11903== by 0x4DCC8ED: clone (in /lib/tls/i686/cmov/libc-2.3.6.so)
==11903== Address 0x52D7DC8 is 16 bytes inside a block of size 48 free'd
==11903== at 0x401D304: operator delete(void*) (vg_replace_malloc.c:246)
==11903== by 0x7976F40: ChromaKeyThread::~ChromaKeyThread() (chromakey.C:300)
==11903== by 0x79797D7: ChromaKey::~ChromaKey() (chromakey.C:553)
==11903== by 0x82B797F: PluginServer::close_plugin() (pluginserver.C:303)
==11903== by 0x82B79BF: PluginServer::~PluginServer() (pluginserver.C:98)
==11903== by 0x8241200: MWindow::hide_plugin(Plugin*, int) (mwindow.C:1511)
==11903== by 0x82B9990: PluginServer::client_side_close()
(pluginserver.C:318)
==11903== by 0x82B1058: PluginClient::client_side_close()
(pluginclient.C:176)
==11903== by 0x797703A: ChromaKeyThread::run() (chromakey.C:316)
==11903== by 0x46B3FE4: Thread::entrypoint(void*) (in
/usr/lib/libguicast.so.1.0.0)
==11903== by 0x4BDBE5F: start_thread (in
/lib/tls/i686/cmov/libpthread-2.3.6.so)
==11903== by 0x4DCC8ED: clone (in /lib/tls/i686/cmov/libc-2.3.6.so)
So, inside
==11903== by 0x797703A: ChromaKeyThread::run() (chromakey.C:316)
the destructor for itself:
==11903== by 0x7976F40: ChromaKeyThread::~ChromaKeyThread() (chromakey.C:300)
was being called... which is obviously a bug and recepie for trobule
No matter what ::run does, it ends at the end of Thread::entrypoint where
another deletion may happen if some other thread races to take the deleted
memory and maybe sets autodelete variabile to nonzero...
This patch fixes this bug by using autodelete property on ChromaKeyThread, and
lets it run out by itself...
Even though it looks sketchy at first, it is not, since it also uses join()
which waits only when it is not called on the thread itself.
bye
andraz
--- hvirtual-cvs/cinelerra/pluginclient.h 2006-05-19 09:52:50.000000000 +0200
+++ hvirtual-2/cinelerra/pluginclient.h 2006-05-31 20:41:50.000000000 +0200
@@ -62,16 +62,14 @@
void run(); \
window_class *window; \
plugin_class *plugin; \
- Condition *completion; \
};
#define PLUGIN_THREAD_OBJECT(plugin_class, thread_class, window_class) \
thread_class::thread_class(plugin_class *plugin) \
- : Thread(0, 0, 0) \
+ : Thread(0, 0, 1) \
{ \
this->plugin = plugin; \
- completion = new Condition(0, "thread_class::completion"); \
} \
\
thread_class::~thread_class() \
@@ -90,7 +88,6 @@
/* Only set it here so tracking doesn't update it until everything is created. */ \
plugin->thread = this; \
int result = window->run_window(); \
- completion->unlock(); \
/* This is needed when the GUI is closed from itself */ \
if(result) plugin->client_side_close(); \
}
@@ -118,11 +115,12 @@
if(thread) \
{ \
/* This is needed when the GUI is closed from elsewhere than itself */ \
+/* Since we now use autodelete, this is all that has to be done, thread will take care of itself ... */ \
+/* Thread join will wait if this was not called from the thread itself or go on if it was */ \
thread->window->lock_window("PLUGIN_DESTRUCTOR_MACRO"); \
thread->window->set_done(0); \
thread->window->unlock_window(); \
- thread->completion->lock("PLUGIN_DESTRUCTOR_MACRO"); \
- delete thread; \
+ thread->join(); \
} \
\
\