Results 1 to 4 of 4

Thread: Strange problem with QThread

  1. #1
    Join Date
    May 2013
    Posts
    2
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Strange problem with QThread

    Hello!

    I'm writing a small program in Qt 5.0 under Windows 7 with msvc2010 toolchain. But in the process of writing I met a rather problem: Exception. Access violation - code c0000005.
    Created a test project that enclose below.
    The problem as follows:
    I'm creating a "thread", in which a "test" is being perfomed. "Test" creates another "thread", which runs in an endless cycle of reading. In the test I create CCANReceiver, which begins to read data from the device, and then send the data. I wait for 5 seconds and close the thread with CCANReceiver. But when trying to call StopReceiving () function while calling IsRunning () I get the exception. Empirically I found that if a function ReadDMADataOneBlock
    ReadDMADataOneBlock () - function of libraries provided by me to work with the device. The source codes are available.
    Source code in attachment. I do not include the library, because without the device driver and it will not work, but I can put the source code.

    Detailed error information:
    (d08.d68): Access violation - code c0000005 (first chance)
    s
    sException at 0x6704c87c, code: 0xc0000005: write access violation at: 0x1, flags=0x0 (first chance) at q:\qt5_workdir\w\s\qtbase\src\corelib\arch\qatomic _msvc.h:351
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=00000000 ebx=00000000 ecx=00000001 edx=00000040 esi=00000007 edi=01d6dfc4
    eip=6704c87c esp=01d6d444 ebp=01d6d444 iopl=0 nv up ei pl nz na pe nc
    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
    Qt5Cored!QAtomicOps<QMutexData *>::testAndSetRelaxed+0xc:
    3516704c87c f00fb10a lock cmpxchg dword ptr [edx],ecx ds:0023:00000040=????????
    Call stack at the moment of program down:
    0 QAtomicOps<QMutexData *>::testAndSetRelaxed qatomic_msvc.h 351 0x6704c87c
    1 QGenericAtomicOps<QAtomicOps<QMutexData *> >::testAndSetAcquire<QMutexData *,QMutexData *> qgenericatomic.h 150 0x6704a8a5
    2 QBasicAtomicPointer<QMutexData>::testAndSetAcquire qbasicatomic.h 229 0x67048e08
    3 QBasicMutex::fastTryLock qmutex.h 87 0x670486f7
    4 QMutex::lock qmutex.cpp 212 0x67069e11
    5 QMutexLocker::QMutexLocker qmutex.h 133 0x670487e8
    6 QThread::isRunning qthread.cpp 448 0x67070243
    7 CCANReceiver::StopReceiving ccanreceiver.cpp 45 0x41c5e3
    I do not understand how this could happen.
    Debugging, I found out that this is most likely due to the fact that QScopedPointer >::data returns a value of 0.
    Call stack:
    0 QScopedPointer<QObjectData,QScopedPointerDeleter<Q ObjectData> >::data qscopedpointer.h 135 0x67041d4c
    1 qGetPtrHelper<QScopedPointer<QObjectData,QScopedPo interDeleter<QObjectData> > > qglobal.h 991 0x670581ab
    2 QThread::d_func qthread.h 136 0x670573d3
    3 QThread::isRunning qthread.cpp 446 0x67070231
    4 CCANReceiver::StopReceiving ccanreceiver.cpp 44 0x420423
    5 CTest0::OnTimerTimeOut ctest0.cpp 324 0x41580e
    Some source code:
    ctest0.h
    Qt Code:
    1. #ifndef CTEST0_H
    2. #define CTEST0_H
    3.  
    4. #include "itest.h"
    5. #include "CANDeviceEx.h"
    6. #include "ccanreceiver.h"
    7. #include <QTimer>
    8.  
    9. class CTest0 : public ITest
    10. {
    11. Q_OBJECT
    12. public:
    13. CTest0(ILogger* _Logger);
    14. virtual void SetFeature(quint64 NumFeat, quint64 ValFeat);
    15. public slots:
    16. virtual void Run();
    17. void OnTimerTimeOut();
    18. public:
    19. virtual QString GetName() const;
    20. virtual ~CTest0();
    21.  
    22. private:
    23. CCANDeviceEx CANDevice;
    24. CCANReceiver *CANReceiver;
    25.  
    26. quint32 sendbuff[3];
    27. QTimer* Timer;
    28.  
    29. quint32 mode1, mode2, sendchannel, bufnum;
    30. quint8 brp1, sjw1, sam1, btlmode1, phseg11, phseg21, prseg1, wakfil1;
    31. quint8 brp2, sjw2, sam2, btlmode2, phseg12, phseg22, prseg2, wakfil2;
    32. };
    33.  
    34. #endif // CTEST0_H
    To copy to clipboard, switch view to plain text mode 
    ctest0.cpp
    Qt Code:
    1. #include "ctest0.h"
    2.  
    3. CTest0::CTest0(ILogger* _Logger) :
    4. ITest(_Logger),
    5. CANReceiver(NULL),
    6. Timer(NULL)
    7. {
    8. }
    9.  
    10. void CTest0::Run()
    11. {
    12. quint32 tmp = 0;
    13. quint32 tmpmode = 0;
    14. sendbuff[0] = 0x01020304;
    15. sendbuff[1] = 0x05060708;
    16. sendbuff[2] = 0x090A0B0C;
    17.  
    18. if (CANReceiver != NULL)
    19. {
    20. delete CANReceiver;
    21. CANReceiver = NULL;
    22. }
    23.  
    24. if (Timer != NULL)
    25. {
    26. delete Timer;
    27. Timer = NULL;
    28. }
    29.  
    30. if (CANDevice.IsOpen())
    31. CANDevice.Close();
    32.  
    33. Timer = new QTimer;
    34.  
    35. QObject::connect(Timer, SIGNAL(timeout()), /*qobject_cast<CTest0*>*/(this), SLOT(OnTimerTimeOut()));
    36. QObject::connect(Timer, SIGNAL(qr()), this, SLOT(OnTimerTimeOut()));
    37. Timer->setInterval(5000);
    38. Timer->setSingleShot(true);
    39.  
    40. /* ... */
    41.  
    42. Logger->AddToLog("Trying to receive data");
    43.  
    44. CANReceiver = new CCANReceiver(&CANDevice);
    45. CANReceiver->StartReceiving();
    46.  
    47. Logger->AddToLog("Start 5s wait");
    48.  
    49. Timer->start();
    50.  
    51. Logger->AddToLog("Trying to send data over " + QString::number(sendchannel) + QString::number(bufnum));
    52.  
    53. if ((tmp = CANDevice.SendData(sendchannel, bufnum, 0, sendbuff, 12)) != 1)
    54. {
    55. SetError("Can't send data, error = " + QString::number(tmp));
    56. Timer->stop();
    57. emit TestEnd();
    58. return;
    59. }
    60.  
    61. Logger->AddToLog("Send " + QString::number(sizeof(sendbuff)) + " bytes");
    62. }
    63.  
    64. void CTest0::SetFeature(quint64 NumFeat, quint64 ValFeat)
    65. {
    66. switch (NumFeat)
    67. {
    68. case 0:
    69. mode1 = ValFeat;
    70. break;
    71.  
    72. case 1:
    73. mode2 = ValFeat;
    74. break;
    75.  
    76. /* ... */
    77.  
    78. case 19:
    79. bufnum = ValFeat;
    80. break;
    81.  
    82. default:
    83. break;
    84. }
    85. }
    86.  
    87. CTest0::~CTest0()
    88. {
    89. if (CANDevice.IsOpen())
    90. CANDevice.Close();
    91.  
    92. if (CANReceiver != NULL)
    93. delete CANReceiver;
    94.  
    95. if (Timer != NULL)
    96. delete Timer;
    97. }
    98.  
    99. QString CTest0::GetName() const
    100. {
    101. return "Test 0";
    102. }
    103.  
    104. void CTest0::OnTimerTimeOut()
    105. {
    106. Logger->AddToLog("Stop 5s wait");
    107.  
    108. CANReceiver->StopReceiving();
    109.  
    110. if (!CANReceiver->GetLastError().isEmpty())
    111. {
    112. SetError("Can't receive data, error \"" + CANReceiver->GetLastError() + "\"");
    113. emit TestEnd();
    114. return;
    115. }
    116.  
    117. Logger->AddToLog("Succesfully receive " + QString::number(CANReceiver->GetBufferSize()) + " bytes");
    118.  
    119. }
    To copy to clipboard, switch view to plain text mode 
    ccanreceiver.h
    Qt Code:
    1. #ifndef CCANRECEIVER_H
    2. #define CCANRECEIVER_H
    3.  
    4. #include <QList>
    5. #include "clasterror.h"
    6. #include "CANDeviceEx.h"
    7. #include <QThread>
    8. #include "CANHeader.h"
    9.  
    10. class CCANReceiver;
    11.  
    12. class CCANReceiverHelper : public QObject, public CLastError
    13. {
    14. Q_OBJECT
    15. public:
    16. CCANReceiverHelper(CCANReceiver* _CANReceiver, CCANDeviceEx* _CANDevice);
    17. ~CCANReceiverHelper();
    18. void StopWork();
    19.  
    20. public slots:
    21. void DoWork();
    22.  
    23. private:
    24. CCANReceiver* CANReceiver;
    25. CCANDeviceEx* CANDevice;
    26. bool Stopped;
    27. _MSG_INPUT rcvblock;
    28. };
    29.  
    30. class CCANReceiver : public CLastError
    31. {
    32. public:
    33. CCANReceiver(CCANDeviceEx* _CANDevice);
    34. ~CCANReceiver();
    35.  
    36. void ClearBuffer();
    37. QList<quint8> GetBuffer() const;
    38. quint64 GetBufferSize() const;
    39. void StartReceiving();
    40. void StopReceiving();
    41. friend class CCANReceiverHelper;
    42.  
    43. private:
    44. void AddToBuffer(quint8 data);
    45.  
    46. private:
    47. QList<quint8> buffer;
    48. CCANReceiverHelper CANReceiverHelper;
    49. QThread CANReceiverHelperThread;
    50. };
    To copy to clipboard, switch view to plain text mode 
    ccanreceiver.cpp
    Qt Code:
    1. #include "ccanreceiver.h"
    2.  
    3. CCANReceiver::CCANReceiver(CCANDeviceEx *_CANDevice) :
    4. CANReceiverHelper(this, _CANDevice)
    5. {
    6. buffer.clear();
    7. CANReceiverHelper.moveToThread(&CANReceiverHelperThread);
    8. QObject::connect(&CANReceiverHelperThread, SIGNAL(started()), &CANReceiverHelper, SLOT(DoWork()));
    9. }
    10.  
    11. CCANReceiver::~CCANReceiver()
    12. {
    13.  
    14. }
    15.  
    16. void CCANReceiver::ClearBuffer()
    17. {
    18. buffer.clear();
    19. }
    20.  
    21. QList<quint8> CCANReceiver::GetBuffer() const
    22. {
    23. return buffer;
    24. }
    25.  
    26. quint64 CCANReceiver::GetBufferSize() const
    27. {
    28. return buffer.size();
    29. }
    30.  
    31. void CCANReceiver::AddToBuffer(quint8 data)
    32. {
    33. buffer.append(data);
    34. }
    35.  
    36. void CCANReceiver::StartReceiving()
    37. {
    38. if (!CANReceiverHelperThread.isRunning())
    39. CANReceiverHelperThread.start();
    40. }
    41.  
    42. void CCANReceiver::StopReceiving()
    43. {
    44. if (CANReceiverHelperThread.isRunning())
    45. {
    46. CANReceiverHelper.StopWork();
    47. CANReceiverHelperThread.quit();
    48. CANReceiverHelperThread.wait();
    49. }
    50. }
    51.  
    52. CCANReceiverHelper::CCANReceiverHelper(CCANReceiver *_CANReceiver, CCANDeviceEx *_CANDevice) :
    53. CANReceiver(_CANReceiver),
    54. CANDevice(_CANDevice),
    55. Stopped(false)
    56. {
    57.  
    58. }
    59.  
    60. void CCANReceiverHelper::StopWork()
    61. {
    62. Stopped = true;
    63. }
    64.  
    65. CCANReceiverHelper::~CCANReceiverHelper()
    66. {
    67.  
    68. }
    69.  
    70. quint64 fact(quint64 n)
    71. {
    72. if (n <= 1)
    73. return 1;
    74. else
    75. return fact(n - 1) * n;
    76. }
    77.  
    78. void CCANReceiverHelper::DoWork()
    79. {
    80. while (1)
    81. {
    82. quint32 res = 0;
    83. quint32 tmp = 0;
    84.  
    85. do
    86. {
    87. if (Stopped)
    88. return;
    89.  
    90. if ((tmp = CANDevice->GetDMAReadyStatus(&res)) != 1)
    91. {
    92. CANReceiver->SetError("Can't get DMA ready status, error = " + QString::number(tmp));
    93. return;
    94. }
    95. }
    96. while (!res);
    97. if ((tmp = CANDevice->ReadDMADataOneBlock((void*)&rcvblock)) != 1)
    98. {
    99. CANReceiver->SetError("Can't read DMA one block, error = " + QString::number(tmp));
    100. return;
    101. }
    102. for (quint8 i = 0; i < rcvblock.RXB0DLC.DLC; i++)
    103. {
    104. CANReceiver->AddToBuffer(rcvblock.data.all[i]);
    105. }
    106. }
    107. }
    108. #endif // CCANRECEIVER_H
    To copy to clipboard, switch view to plain text mode 

    I beg for your help.
    Sincerely, akaWolf.


    Added after 8 minutes:


    I described this problem before, but no one could help me.
    Attached Files Attached Files
    Last edited by akaWolf; 30th May 2013 at 11:51.

  2. The following user says thank you to akaWolf for this useful post:


  3. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Strange problem with QThread

    The code looks very fragile, it access data from different threads without any protection.

    To further simplify the problem I would recommend getting rid of the outer thread.

    Cheers,
    _

  4. The following user says thank you to anda_skoa for this useful post:


  5. #3
    Join Date
    May 2013
    Posts
    2
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Strange problem with QThread

    Thank you, I've already solved this problem: it was problem with my colleauge's library because it wrote where it shouldn't. This bug happened to be very covert and i could recognize it long time ago after wrong piece of code was executed..

  6. The following user says thank you to akaWolf for this useful post:


  7. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Strange problem with QThread

    Ah, good

    Btw, you don't need to check a pointer before calling delete on it, delete 0 is perfectly fine for C++.

    Cheers,
    _

Similar Threads

  1. Strange Problem
    By Atomic_Sheep in forum General Programming
    Replies: 3
    Last Post: 7th February 2013, 10:57
  2. Replies: 1
    Last Post: 4th October 2012, 14:49
  3. Strange problem
    By wirasto in forum Qt Programming
    Replies: 3
    Last Post: 27th December 2009, 11:24
  4. Strange problem
    By pavel in forum Newbie
    Replies: 4
    Last Post: 18th December 2009, 21:46
  5. Very Strange problem
    By dreamer in forum Qt Programming
    Replies: 1
    Last Post: 30th April 2008, 09:20

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.