【问题标题】:Qt deleteLater causes crash when time is changedQt deleteLater 在时间更改时导致崩溃
【发布时间】:2017-09-14 15:08:54
【问题描述】:

我们创建了一个从 QTcpServer 派生的 Qt HTTP 服务器。 每个传入的客户端连接都在一个新线程中处理,如下所示:

    void WebClientThread::run()
    {

        // Configure the web client socket
        m_socket = new QTcpSocket();

       connect(m_socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
       connect(m_socket, SIGNAL (error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));

      // Create the actual web client = worker
      WebClient client(m_socket, m_configuration, m_pEventConnection, m_pThumbnailStreams, m_server, m_macAddress, 0 );

     // Thread event loop
     exec();

     m_pLog->LOG(L_INFO, "Webclient thread finished");
   }
   //
   // Client disconnect
   //
   void WebClientThread::disconnected()
   {
       m_socket->deleteLater();
       exit(0);
   }

此代码有效,但是当我们设备的 NTP 连接启动并且系统时间从 1970 年 1 月 1 日更正到当前时间时,我们遇到了应用程序崩溃。 在运行应用程序并同时通过脚本更改系统时间时,也可能会重现崩溃。

应用程序运行良好 - 即使系统时间像这样即时更改:

void WebClientThread::run()
{

    // Configure the web client socket
    m_socket = new QTcpSocket();

    connect(m_socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
    connect(m_socket, SIGNAL (error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));

    // Create the actual web client = worker
    WebClient client(m_socket, m_configuration, m_pEventConnection, m_pThumbnailStreams, m_server, m_macAddress, 0 );

    // Make this thread a loop,
    exec();

    delete m_socket;

    m_pLog->LOG(L_INFO, "Webclient thread finished");

}


//=======================================================================
//
// Client disconnect
//
void WebClientThread::disconnected()
{
    exit(0);
}

为什么deleteLater()会在系统时间偏移时使应用程序崩溃?


附加信息:

操作系统 = 嵌入式 linux 3.0.0。 Qt = 4.8

套接字是我们的 Qt Web 服务器应用程序和前端服务器之间的连接 = lighttpd。会不会是lighttpd在系统时移47年的时候关闭了socket,而我们的web服务器还在处理这个请求?

我可以通过向服务器发送请求来重现它,同时并行运行将日期设置为 1980、1990 和 2000 的脚本。它每秒更改一次。

【问题讨论】:

  • 您能为此写一个MCVE吗?另外,请写下您什么时候准确更改系统时间以重现该错误...
  • 我写了一个minimal example,它使用deleteLater 的方式与您的用法相似(如果我理解正确的话)。该示例运行良好,并在我的 Windows 7 机器上的 Qt 5.6.2 和 Qt 5.9.1 上产生了预期的输出。您确定问题与您使用deleteLater 的方式有关吗?也许是你的代码中的其他东西导致了 UB...
  • valgrind-ed 了吗?

标签: multithreading qt


【解决方案1】:

这有错误使用 Qt 线程的味道。我建议你不要继承QThread,如果你从它的run()方法调用exec(),因为如果你这样做太容易做错事了。

例如查看https://wiki.qt.io/QThreads_general_usage 以了解如何为QThread 设置工作者QObject,但要点是,创建QObject 的子类和把你的代码放在那里。然后将它的一个实例移动到QThread 实例,并连接信号和槽以使事情发生。

另外,您通常不应该将线程用于 Qt 网络,例如 QTcpSocket。 Qt 是基于事件和异步的,只要你只使用信号和槽并且从不在你的槽方法中阻塞,就不需要线程,它们只会使事情复杂化而没有任何好处。只有当你的计算很耗时,或者你的程序确实需要利用多个 CPU 内核来获得足够好的性能时,才考虑使用多线程。

【讨论】:

    猜你喜欢
    • 2012-03-22
    • 1970-01-01
    • 2015-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多