Вызов luaL_error в другом потоке вызывает qWarning - PullRequest
0 голосов
/ 28 октября 2018

При вызове luaL_error() в состоянии lua, работающем в отдельном потоке от графического интерфейса, выводится предупреждение QObject::~QObject: Timers cannot be stopped from another thread и приложение закрывается.

После большого количества испытаний я смог воспроизвестиэто в компактном примере программы, имитирующей мой текущий рабочий процесс.Ниже приведен код:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <QThread>
#include "lua_src/lua.hpp"

class Worker : public QObject
{
    Q_OBJECT
public:
    Worker() : QObject(){}

public slots:
    void process()
    {
        lua_State *L = luaL_newstate();
        luaL_dostring(L, "x=5");
        luaL_error(L, "test error");
        lua_close(L);
        emit finished();
    }

signals:
    void finished();
};

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    Worker *worker;
    QThread *workerThread;
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    worker = new Worker();
    workerThread = new QThread();
    worker->moveToThread(workerThread);
    connect(workerThread, SIGNAL(started()), worker, SLOT(process()));
    connect(worker, SIGNAL(finished()), workerThread, SLOT(quit()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
    workerThread->start();
}

MainWindow::~MainWindow()
{
    delete ui;
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

Я бы хотелОжидается, что процесс рабочего потока продолжится, а состояние lua просто закроется.Однако это делает обработку ошибок lua ​​бесполезной.Я включил исходный код Lua 5.3 для этого проекта.

Одна вещь, которую я заметил, заключается в том, что эта проблема возникает только для приложений с графическим интерфейсом, а не консольных приложений.

Кто-нибудь знает, чточто здесь происходит и как обрабатывать ошибки lua из QThread?Спасибо за ваше время.

1 Ответ

0 голосов
/ 29 октября 2018

В документации для luaL_error указано:

Эта функция никогда не возвращается, ...

В других местах документация по обработке ошибок lua ​​имеет:

Если ошибка происходит вне какой-либо защищенной среды, Lua вызывает функцию паники (см. Lua_atpanic), а затем вызывает прерывание, таким образом выходя из хост-приложения.Ваша функция паники может избежать этого выхода, никогда не возвращаясь (например, делая длинный прыжок к вашей собственной точке восстановления за пределами Lua).

Таким образом, вы можете думать о luaL_errorlua_error) какподнимая фатальные ошибки.Они фатальны для скрипта в защищенном режиме или фатальны для вашего процесса вне защищенного режима.

Если ваш код C вызывается из скрипта, вы можете запустить скрипт в защищенном режиме с помощью lua_pcall,Это обычный случай.Если ваш код C не вызывается из скрипта, то, вероятно, вы не захотите использовать luaL_error, поскольку его основным преимуществом является предоставление информации о том, где произошла ошибка в скрипте.

Вы также можете получить информациюо местонахождении ошибки с помощью luaL_where и сообщить об этом пользователю другим способом.

...