Unix signals and QCharts cause application blocking
-
@tovax
It will certainly block the UI for as long as the parameter. It ought not block it "forever", but I don't know if there is something about the way they are handling Linux signals for which this is problematic. -
@tovax
It will certainly block the UI for as long as the parameter. It ought not block it "forever", but I don't know if there is something about the way they are handling Linux signals for which this is problematic.@JonB
I have updated github and added a simple driver.
JCDemoDriver
Both the application and driver have been tested on Ubuntu.
The previous version was tested on IMX6U+Linux, and is the same as the Ubuntu platform, with applications permanently frozen. -
@JonB
I have updated github and added a simple driver.
JCDemoDriver
Both the application and driver have been tested on Ubuntu.
The previous version was tested on IMX6U+Linux, and is the same as the Ubuntu platform, with applications permanently frozen.@tovax
Your timer times out every 100ms, and in the slot you sleep for 100ms. This may not be a good combination. This implies it will be close to permanently sleeping: as soon the sleep terminates the next timer timeout will occur and go back into sleep more or less immediately. BTW, if you expect the timer timeout to only start counting again after the sleep, that's not the way it works. I suggest any sleep needs at least to be for a lesser period than the repeated time outs, e.g. no more than 50 for a timeout of 100? -
@tovax
Your timer times out every 100ms, and in the slot you sleep for 100ms. This may not be a good combination. This implies it will be close to permanently sleeping: as soon the sleep terminates the next timer timeout will occur and go back into sleep more or less immediately. BTW, if you expect the timer timeout to only start counting again after the sleep, that's not the way it works. I suggest any sleep needs at least to be for a lesser period than the repeated time outs, e.g. no more than 50 for a timeout of 100?@JonB
According to your suggestion, I retested it. Without a driver, there is no problem that the sleep time is greater than the timer period. For example, a timer cycle of 100 milliseconds and a sleep period of 200 milliseconds do not cause freezing. This causes the timerEvent to be counted every 200 milliseconds. -
@JonB
According to your suggestion, I retested it. Without a driver, there is no problem that the sleep time is greater than the timer period. For example, a timer cycle of 100 milliseconds and a sleep period of 200 milliseconds do not cause freezing. This causes the timerEvent to be counted every 200 milliseconds.@tovax
I would start by seeing whether in your case theactivated()
signals are being emitted and whether thehandleSig...()
slots are getting called at all.
And with judicious placement ofqDebug()
statements you may be able to find where it is "freezing". -
@tovax
I would start by seeing whether in your case theactivated()
signals are being emitted and whether thehandleSig...()
slots are getting called at all.
And with judicious placement ofqDebug()
statements you may be able to find where it is "freezing".@JonB
I can only make sure that the driver is working correctly at the time of the freeze, and I don't know what state the socket is in. Can you give me some guidance? The thread pool was tested yesterday, and the sub threads did not output when it was frozen. -
@JonB
I can only make sure that the driver is working correctly at the time of the freeze, and I don't know what state the socket is in. Can you give me some guidance? The thread pool was tested yesterday, and the sub threads did not output when it was frozen. -
@tovax
Your timer times out every 100ms, and in the slot you sleep for 100ms. This may not be a good combination. This implies it will be close to permanently sleeping: as soon the sleep terminates the next timer timeout will occur and go back into sleep more or less immediately. BTW, if you expect the timer timeout to only start counting again after the sleep, that's not the way it works. I suggest any sleep needs at least to be for a lesser period than the repeated time outs, e.g. no more than 50 for a timeout of 100?@JonB said in Unix signals and QCharts cause application blocking:
@tovax
Your timer times out every 100ms, and in the slot you sleep for 100ms. This may not be a good combination. This implies it will be close to permanently sleeping: as soon the sleep terminates the next timer timeout will occur and go back into sleep more or less immediately. BTW, if you expect the timer timeout to only start counting again after the sleep, that's not the way it works. I suggest any sleep needs at least to be for a lesser period than the repeated time outs, e.g. no more than 50 for a timeout of 100?In the case of driving working, it is indeed a critical value for sleep time to be equal to the timing period. When the sleep time is less than the timing period, the test is no problem. When the sleep time is greater than or equal to the timing period, it can cause the application to freeze forever.
When the driver is not working, the sleep time is independent of the timing cycle, and the application works normally.
-
@JonB said in Unix signals and QCharts cause application blocking:
@tovax
Your timer times out every 100ms, and in the slot you sleep for 100ms. This may not be a good combination. This implies it will be close to permanently sleeping: as soon the sleep terminates the next timer timeout will occur and go back into sleep more or less immediately. BTW, if you expect the timer timeout to only start counting again after the sleep, that's not the way it works. I suggest any sleep needs at least to be for a lesser period than the repeated time outs, e.g. no more than 50 for a timeout of 100?In the case of driving working, it is indeed a critical value for sleep time to be equal to the timing period. When the sleep time is less than the timing period, the test is no problem. When the sleep time is greater than or equal to the timing period, it can cause the application to freeze forever.
When the driver is not working, the sleep time is independent of the timing cycle, and the application works normally.
-
@tovax
Put regularqDebug()
statements intounixSignalHandler()
&qtSignalHandler()
, and also intimerEvent()
, say between every line, and see what the last output you get was.@JonB said in Unix signals and QCharts cause application blocking:
@tovax
Put regularqDebug()
statements intounixSignalHandler()
&qtSignalHandler()
, and also intimerEvent()
, say between every line, and see what the last output you get was.void PanelDriver::unixSignalHandler(int) { qDebug() << __FUNCTION__ << 0; char a = 1; ::write(mSocketFd[0], &a, sizeof(a)); qDebug() << __FUNCTION__ << 1; } void PanelDriver::qtSignalHandler() { qDebug() << __FUNCTION__ << 0; mSocketNotifier->setEnabled(false); qDebug() << __FUNCTION__ << 1; char tmp; ::read(mSocketFd[1], &tmp, sizeof(tmp)); qDebug() << __FUNCTION__ << 2; // do Qt stuff static int cnt = 0; qDebug() << __FUNCTION__ << cnt++; emit panelChanged(); qDebug() << __FUNCTION__ << 3; mSocketNotifier->setEnabled(true); qDebug() << __FUNCTION__ << 4; }
debug output:
unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 1 timerEvent QTime("18:43:29.352") qtSignalHandler 0 qtSignalHandler 1 qtSignalHandler 2 qtSignalHandler 56 qtSignalHandler 3 qtSignalHandler 4 unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0
From the debugging output, the possible problem is:
:: write (mSocketFd [0],&a, sizeof (a));
-
@tovax
TheQTimer
you are using is not precisely "accurate". If you rely on it being exactly 100ms that is not good.If I were you I would still want to know where/why the "freeze" occurs.
@JonB said in Unix signals and QCharts cause application blocking:
@tovax
TheQTimer
you are using is not precisely "accurate". If you rely on it being exactly 100ms that is not good.If I were you I would still want to know where/why the "freeze" occurs.
Yes, I particularly want to know why this abnormal freezing occurs.
-
@JonB said in Unix signals and QCharts cause application blocking:
@tovax
Put regularqDebug()
statements intounixSignalHandler()
&qtSignalHandler()
, and also intimerEvent()
, say between every line, and see what the last output you get was.void PanelDriver::unixSignalHandler(int) { qDebug() << __FUNCTION__ << 0; char a = 1; ::write(mSocketFd[0], &a, sizeof(a)); qDebug() << __FUNCTION__ << 1; } void PanelDriver::qtSignalHandler() { qDebug() << __FUNCTION__ << 0; mSocketNotifier->setEnabled(false); qDebug() << __FUNCTION__ << 1; char tmp; ::read(mSocketFd[1], &tmp, sizeof(tmp)); qDebug() << __FUNCTION__ << 2; // do Qt stuff static int cnt = 0; qDebug() << __FUNCTION__ << cnt++; emit panelChanged(); qDebug() << __FUNCTION__ << 3; mSocketNotifier->setEnabled(true); qDebug() << __FUNCTION__ << 4; }
debug output:
unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 1 timerEvent QTime("18:43:29.352") qtSignalHandler 0 qtSignalHandler 1 qtSignalHandler 2 qtSignalHandler 56 qtSignalHandler 3 qtSignalHandler 4 unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0
From the debugging output, the possible problem is:
:: write (mSocketFd [0],&a, sizeof (a));
@tovax
The fact that you show manyunixSignalHandler 0
in a row with no alternatingunixSignalHandler 1
in between (like it does to start out with) means that you keep re-enteringunixSignalHandler()
, writing a byte, and then not even completing thewrite()
because you don't see the1
output.I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the
write()
will complete and the Qt handler willread()
after eachwrite()
before the next one. Which for whatever reason is not happening in your case. -
@tovax
The fact that you show manyunixSignalHandler 0
in a row with no alternatingunixSignalHandler 1
in between (like it does to start out with) means that you keep re-enteringunixSignalHandler()
, writing a byte, and then not even completing thewrite()
because you don't see the1
output.I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the
write()
will complete and the Qt handler willread()
after eachwrite()
before the next one. Which for whatever reason is not happening in your case.@JonB said in Unix signals and QCharts cause application blocking:
@tovax
The fact that you show manyunixSignalHandler 0
in a row with no alternatingunixSignalHandler 1
in between (like it does to start out with) means that you keep re-enteringunixSignalHandler()
, writing a byte, and then not even completing thewrite()
because you don't see the1
output.I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the
write()
will complete and the Qt handler willread()
after eachwrite()
before the next one. Which for whatever reason is not happening in your case.Based on your analysis and debugging output, I added a mutex, but the result is the same. I cannot understand it.
void PanelDriver::unixSignalHandler(int) { qDebug() << __FUNCTION__ << 0; QMutexLocker locker(&mMutex); char a = 1; ::write(mSocketFd[0], &a, sizeof(a)); qDebug() << __FUNCTION__ << 1; }
debug output:
unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 1 timerEvent QTime("19:13:56.243") qtSignalHandler 0 qtSignalHandler 1 qtSignalHandler 2 qtSignalHandler 63 qtSignalHandler 3 qtSignalHandler 4 unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 1 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0
-
@tovax
The fact that you show manyunixSignalHandler 0
in a row with no alternatingunixSignalHandler 1
in between (like it does to start out with) means that you keep re-enteringunixSignalHandler()
, writing a byte, and then not even completing thewrite()
because you don't see the1
output.I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the
write()
will complete and the Qt handler willread()
after eachwrite()
before the next one. Which for whatever reason is not happening in your case.@JonB said in Unix signals and QCharts cause application blocking:
@tovax
The fact that you show manyunixSignalHandler 0
in a row with no alternatingunixSignalHandler 1
in between (like it does to start out with) means that you keep re-enteringunixSignalHandler()
, writing a byte, and then not even completing thewrite()
because you don't see the1
output.I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the
write()
will complete and the Qt handler willread()
after eachwrite()
before the next one. Which for whatever reason is not happening in your case.Using the enable flag has the same result.
void PanelDriver::unixSignalHandler(int) { qDebug() << __FUNCTION__ << 0; #if 0 QMutexLocker locker(&mMutex); #else static bool enable = true; if (!enable) return; #endif enable = false; char a = 1; ::write(mSocketFd[0], &a, sizeof(a)); enable = true; qDebug() << __FUNCTION__ << 1; }
-
@tovax
The fact that you show manyunixSignalHandler 0
in a row with no alternatingunixSignalHandler 1
in between (like it does to start out with) means that you keep re-enteringunixSignalHandler()
, writing a byte, and then not even completing thewrite()
because you don't see the1
output.I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the
write()
will complete and the Qt handler willread()
after eachwrite()
before the next one. Which for whatever reason is not happening in your case.@JonB said in Unix signals and QCharts cause application blocking:
@tovax
The fact that you show manyunixSignalHandler 0
in a row with no alternatingunixSignalHandler 1
in between (like it does to start out with) means that you keep re-enteringunixSignalHandler()
, writing a byte, and then not even completing thewrite()
because you don't see the1
output.I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the
write()
will complete and the Qt handler willread()
after eachwrite()
before the next one. Which for whatever reason is not happening in your case.It is also a failure, and continuous output "unixSignalHandler 0" after freezing.
void PanelDriver::unixSignalHandler(int) { qDebug() << __FUNCTION__ << 0; #if 0 QMutexLocker locker(&mMutex); #else if (!enable) return; #endif enable = false; char a = 1; ::write(mSocketFd[0], &a, sizeof(a)); qDebug() << __FUNCTION__ << 1; } void PanelDriver::qtSignalHandler() { qDebug() << __FUNCTION__ << 0; mSocketNotifier->setEnabled(false); qDebug() << __FUNCTION__ << 1; char tmp; ::read(mSocketFd[1], &tmp, sizeof(tmp)); qDebug() << __FUNCTION__ << 2; // do Qt stuff static int cnt = 0; qDebug() << __FUNCTION__ << cnt++; emit panelChanged(); qDebug() << __FUNCTION__ << 3; mSocketNotifier->setEnabled(true); qDebug() << __FUNCTION__ << 4; enable = true; }
-
Perform a write test on the socketpair. Each time, 278 (0~277) pieces of data are written and then frozen.
int cnt = 0; while (true) { char a = 1; ::write(mSocketFd[0], &a, sizeof(a)); qDebug() << __FUNCTION__ << cnt++; }
debug output:
PanelDriver 0 PanelDriver 1 PanelDriver 2 PanelDriver 3 ... ... ... PanelDriver 273 PanelDriver 274 PanelDriver 275 PanelDriver 276 PanelDriver 277
-
It may not be caused by the socket write buffer being full. It seems that after the socket was written, the activate() signal was not triggered, causing the socket to be unable to read in time, and then causing the socket write buffer to be full.
However, I have already processed all events in timerEvent, and I don't know why there is still a freeze. More strangely, from the debug output information, it can be seen that the exception occurred at the moment the timerEvent returned.
void PanelDriver::unixSignalHandler(int) { qDebug() << __FUNCTION__ << 0; char a = 1; ::write(mSocketFd[0], &a, sizeof(a)); mBufferCounter++; qDebug() << __FUNCTION__ << 1 << mBufferCounter; } void PanelDriver::qtSignalHandler() { mSocketNotifier->setEnabled(false); char tmp; ::read(mSocketFd[1], &tmp, sizeof(tmp)); mBufferCounter--; qDebug() << __FUNCTION__ << mBufferCounter; mSocketNotifier->setEnabled(true); } void JCDemoDriver::timerEvent(QTimerEvent *event) { if (event->timerId() != mTimerId) { qDebug() << __FUNCTION__ << __LINE__; QWidget::timerEvent(event); return; } static int cnt = 0; #if 0 qDebug() << __FUNCTION__ << cnt++; #else label->setText(QString::number(cnt++)); #endif int ms = 0; do { QThread::msleep(1); QCoreApplication::processEvents(); if (ms % 10 == 0) qDebug() << __FUNCTION__ << ms; } while ((ms++) < 100); qDebug() << __FUNCTION__ << QTime::currentTime(); }
debug output:
timerEvent 0 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 timerEvent 10 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 timerEvent 20 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 timerEvent 30 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 timerEvent 40 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 timerEvent 50 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 timerEvent 60 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 timerEvent 70 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 timerEvent 80 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 timerEvent 90 unixSignalHandler 0 unixSignalHandler 1 1 qtSignalHandler 0 timerEvent 100 timerEvent QTime("11:12:00.360") unixSignalHandler 0 unixSignalHandler 1 1 unixSignalHandler 0 unixSignalHandler 1 2 unixSignalHandler 0 unixSignalHandler 1 3 unixSignalHandler 0 unixSignalHandler 1 4 unixSignalHandler 0 unixSignalHandler 1 5 unixSignalHandler 0 unixSignalHandler 1 6 unixSignalHandler 0 unixSignalHandler 1 7 unixSignalHandler 0 unixSignalHandler 1 8 unixSignalHandler 0 unixSignalHandler 1 9 unixSignalHandler 0 unixSignalHandler 1 10 ... ... ... ... ... ... ... unixSignalHandler 0 unixSignalHandler 1 273 unixSignalHandler 0 unixSignalHandler 1 274 unixSignalHandler 0 unixSignalHandler 1 275 unixSignalHandler 0 unixSignalHandler 1 276 unixSignalHandler 0 unixSignalHandler 1 277 unixSignalHandler 0 unixSignalHandler 1 278 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0 unixSignalHandler 0
-
T tovax referenced this topic on
-
T tovax referenced this topic on
-
It can be determined that the freezing of the application has nothing to do with the reading and writing of the socket. Because just setting the unix signal handler can also cause freezing.
@tovax said in Unix signals and QCharts cause application blocking:
It can be determined that the freezing of the application has nothing to do with the reading and writing of the socket. Because just setting the unix signal handler can also cause freezing.
After making unixSignalHandler() reentrant, socket write blocking is likely to be the main cause of freezing. I am testing and will update the github code in 12 hours.