GUIInvoke takes a QObject* to avoid callbacks after object lifetime

* The GUIInvoke object takes a QObject, and uses QPointer to check that
  it hasn't been deleted when the callback fires. This prevents delayed
  callbacks from executing after the object has been deleted and
  crashing.
* In most cases the pointer is just 'this'.
This commit is contained in:
baldurk
2018-05-08 11:54:34 +01:00
parent c880def5ef
commit 082ab4d75d
25 changed files with 113 additions and 108 deletions
+7 -5
View File
@@ -39,8 +39,9 @@
// on the python thread.
struct CaptureContextInvoker : ICaptureContext
{
PythonShell *m_Shell;
ICaptureContext &m_Ctx;
CaptureContextInvoker(ICaptureContext &ctx) : m_Ctx(ctx) {}
CaptureContextInvoker(PythonShell *shell, ICaptureContext &ctx) : m_Shell(shell), m_Ctx(ctx) {}
virtual ~CaptureContextInvoker() {}
//
///////////////////////////////////////////////////////////////////////
@@ -140,7 +141,7 @@ struct CaptureContextInvoker : ICaptureContext
{
if(!GUIInvoke::onUIThread())
{
GUIInvoke::blockcall([this, ptr, params...]() { (m_Ctx.*ptr)(params...); });
GUIInvoke::blockcall(m_Shell, [this, ptr, params...]() { (m_Ctx.*ptr)(params...); });
return;
}
@@ -154,7 +155,8 @@ struct CaptureContextInvoker : ICaptureContext
if(!GUIInvoke::onUIThread())
{
R ret;
GUIInvoke::blockcall([this, &ret, ptr, params...]() { ret = (m_Ctx.*ptr)(params...); });
GUIInvoke::blockcall(m_Shell,
[this, &ret, ptr, params...]() { ret = (m_Ctx.*ptr)(params...); });
return ret;
}
@@ -447,7 +449,7 @@ PythonShell::PythonShell(ICaptureContext &ctx, QWidget *parent)
{
ui->setupUi(this);
m_ThreadCtx = new CaptureContextInvoker(m_Ctx);
m_ThreadCtx = new CaptureContextInvoker(this, m_Ctx);
QObject::connect(ui->lineInput, &RDLineEdit::keyPress, this, &PythonShell::interactive_keypress);
QObject::connect(ui->helpSearch, &RDLineEdit::keyPress, this, &PythonShell::helpSearch_keypress);
@@ -681,7 +683,7 @@ void PythonShell::on_runScript_clicked()
context->executeString(lit("script.py"), script);
scriptContext = NULL;
GUIInvoke::call([this, context]() {
GUIInvoke::call(this, [this, context]() {
context->Finish();
enableButtons(true);
});