Recently ,I come across this problem as I memtioned in this Title.
I have tried by using QThread::terminate(),but I just can NOT stop
the thread ,which is in a dead loop (let's say,while(1)).
thanks a lot.
Terminating the thread is the easy solution to stopping an async operation, but it is usually a bad idea: the thread could be doing a system call or could be in the middle of updating a data structure when it is terminated, which could leave the program or even the OS in an unstable state.
Try to transform your while(1) into while( isAlive() ) and make isAlive() return false when you want the thread to exit.
QThreads can deadlock if they finish "naturally" during termination.
For example in Unix, if the thread is waiting on a "read" call, the termination attempt (a Unix signal) will make the "read" call abort with an error code before the thread is destroyed.
That means that the thread can still reach it's natural exit point while being terminated. When it does so, a deadlock is reached since some internal mutex is already locked by the "terminate" call.
My workaround is to actually make sure that the thread never returns if it was terminated.
while( read(...) > 0 ) {
// Do stuff...
}
while( wasTerminated )
sleep(1);
return;
wasTerminated here is actually implemented a bit more complex, using atomic ints:
enum {
Running, Terminating, Quitting
};
QAtomicInt _state; // Initialized to Running
void myTerminate()
{
if( _state.testAndSetAquire(Running, Terminating) )
terminate();
}
void run()
{
[...]
while(read(...) > 0 ) {
[...]
}
if( !_state.testAndSetAquire(Running, Quitting) ) {
for(;;) sleep(1);
}
}
Have you tried exit or quit?
Did the thread call QThread::setTerminationEnabled(false)? That would cause thread termination to delay indefinitely.
EDIT: I don't know what platform you're on, but I checked the Windows implementation of QThread::terminate. Assuming the thread was actually running to begin with, and termination wasn't disabled via the above function, it's basically a wrapper around TerminateThread() in the Windows API. This function accepts disrespect from no thread, and tends to leave a mess behind with resource leaks and similar dangling state. If it's not killing the thread, you're either dealing with zombie kernel calls (most likely blocked I/O) or have even bigger problems somewhere.
To use unnamed pipes
int gPipeFdTest[2]; //create a global integer array
As an when where you intend to create pipes use
if( pipe(gPipeFdTest) < 0)
{
perror("Pipe failed");
exit(1);
}
The above code will create a pipe which has two ends gPipeFdTest[0] for reading and gPipeFdTest[1] for writing. What you can do is in your run function set up to read the pipe using select system call. And from where you want to come out of run, there set up to write using write system call. I have used select system call for monitoring the read end of the pipe as it suits my implmentation. Try to figure all this out in your case. If you need any more help, give me a buzz.
Edit:
My problem was just like yours. I had a while(1) loop and the other things I tried needed mutexes and other fancy multithreading mumbo jumbo, which added complexity and debugging was nightmare. Using pipes absolved me from those complexities besides simplified the code. I am not saying that it is the best option but in my case it turned out to be the best and cleanest alternative. I was bugged my hung application before this solution.
Related
I need to kill a process without raising any errors. I need to make distinction between when the process crashed and when the user killed it intentionally. I see that on Windows a command line process can be closed only using .kill() and not .terminate().
If I connect the .errorOccurred(), the function is called even if I intentionally press the button to kill the process. Is there a way to avoid this?
There is QObject::blockSignals(), which temporarily prevents any signal from being emitted.
However, I would avoid using it, and handle it instead in the code that is handling the process.
Two options:
Disconnect the process’ signals before terminating:
m_process.disconnect(this);
m_process.kill();
Remember that you’re in “killing state” and ignore the signal/handle it differently:
m_killingProcess = true; // member variable defaulting to false
m_process.kill();
In the slot connected to errorOccurred:
void Foo::processErrorOccurred(QProcess::ProcessError error)
{
if (m_killingProcess) {
// do nothing?
return;
}
// handle process error (when not killing)
}
using QtCreator to make a loftier interface to a sofware.
There is basically a set of buttons to tune and inputs, a start and stop job
buttons, my problem comes from an infinite loop that freezes the display so I came up with using fork() so that the loop have to compete with the main program instead of eating up the whole resources (no multithreading), but the program crashes spiting:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not
been called
[xcb] Aborting, sorry about that.
a.out: ../../src/xcb_io.c:274: poll_for_event: Assertion
`!xcb_xlib_threads_sequence_lost' failed.
the fonction calling the loop is called 'ON', 'OFF' is supposed to exit the forked process.
//in button 'ON' func
ps = fork();
if(getpid() == ps)
{
while(1)
{
strcpy(word, charset(minlength, maxlength, N));
ui->pass->setText(word);//operation on the display
....SNIP
}
}
//In button 'OFF' func
if(getpid() == ps)
exit(0);
I'm really asking what is the correct way of starting a while(1) and be able to break, exit, or return from it while not freezing the window using QT, thanks.
You crash probably here:
ui->pass->setText(word);//operation on the display
as in Qt, you can not change UI from non UI threads directly. Only from signals and slots mechanism.
The proper way to not freeze UI is obviously to compute lengthy operations in another thread.
You can achieve this in several ways:
One is by sub-classing QObject class to create 'worker object' which would perform all heavy operations. You create new QThread object that should live as long as you need your object. And use QObject::moveToThread method to move created object to new thread. To control your worker object you should send signals from object and call it's slots also via signal-slot mechanism. If you call them directly - they will be executed in caller thread (so do not perform stuff like worker->startHeavyJob(); in UI thread). Instead emit signal in UI (emit sigStartHeavyStuff();) and connect it to slot of your worker object (slotDoHeavyStuff();)
if you do not want to bother with this (if operation is pretty small)
- you can use QApplication::processEvents() to process events in UI event loop while going in your infinite while loop.
Another way is to use QtConcurrentRun framework to run function in separate thread which manages itself. Threads are taken from thread pool and are managed by Qt. This approach looks like something you want to do. Though you still will be able to access UI objects only through signals and slots.
I see one big issue in the presented code that is causing your freeze: You never let Qt process anything while you are in the loop. You need to allow Qt to run it's event loop. The easiest way is to use QApplication::processEvents() inside the loop.
I'm also not a fan of a while(1) loop for a couple of reasons. The first of which is that it can eat machine cycles waiting for things to happen. I doubt you really need to run the code as fast as possible, you could probably get away with some sleeping in your loop.
The other issue is that it is hard to break out. A cleaner approach would be something like this
void MyClass::on_pushButton_ON_clicked()
{
MyClass::done = false; // this is a class attribute
while (!MyClass::done) {
QApplication::processEvents();
//...
}
}
void MyClass::on_pushButton_OFF_clicked()
{
MyClass::done = true;
}
I am working on an Spark project which has an executable which starts the process in background , now I need to know when the process gets killed through Bash.The only solution I got is to continuously check its PID existence through grep in loop if exist or not , Is there any other possible solution that do it without looping around .
I also tried handling the exit codes ,but the exit code is 0 if process runs and only changes when it gets killed which need to be checked continuously
If I understand right, the situation is this:
Your executable does somewhere fork and run another logic in another process, and you want the main process to get notify whether the forked process is still running.
In order to answer I'll make sure we both are familiar with the same terminology:
The main process (when you run your executable) is called the parent process.
The process that the parent process is starting, is called the child process.
Now when a child process dies a signal SIGCHLD is sent to the parent process, Normally SIGCHLD is mapped to SIG_DFL which is actually SIG_IGN for SIGCHLD. In human words, it means that the parent process does not give a shit if the child process dies.
But, If you want to get notify, you may change the behaviour of what happens when SIGCHLD is sent. In order to do so you must implement signal handler function:
void custom_sigchld_handler(int sig)
{
pid_t p;
int status;
while ((p = waitpid(-1, &status, WNOHANG)) != -1)
{
// If you got here it means p is a dead process. Do your logic here...
}
}
Then you must declare that you want our custom_sigchld_handler to take care of SIGCHLD signals:
struct sigaction signal_action = {0};
signal_action.sa_handler = custom_sigchld_handler;
sigaction(SIGCHLD, &signal_action, NULL);
May need a little more context... if your executable is starting the process, there is surely a way to get or keep a handle on it while executing.
In php, there is proc_open(), in Qt there is the QProcess class, in c/c++, there is popen()
Many languages have this feature, but without more details it's hard to offer a solution.
In my user space Linux application, I have a thread which communicated to the main process through a pipe. Below is the code
static void _notify_main(int cond)
{
int r;
int tmp = cond;
r = write( _nfy_fd, &tmp, sizeof(tmp) );
ERROR( "write failed: %d. %s\n", r, strerror(r) );
}
Pretty straight forward. It's been working fine for quite a while now. But recently, the write call will fail with "interrupted system call" error after the programme went under some stress test.
Strangely, the stuff actually went through the pipe no problem. Of course I'd still like to go to the bottom of the error message and get rid of it.
Thanks,
The write(2) man page mentions:
Conforming to
SVr4, 4.3BSD, POSIX.1-2001.
Under SVr4 a write may be interrupted and return EINTR at any point, not just before any data is written.
I guess you were just lucky that it didn't occur so far.
If you google just for the "interrupted system call", you will find this thread which tells you to use siginterrupt() to auto-restart the write call.
From http://www.gnu.org/
A signal can arrive and be handled while an I/O primitive such as open
or read is waiting for an I/O device. If the signal handler returns,
the system faces the question: what should happen next?
POSIX specifies one approach: make the primitive fail right away. The
error code for this kind of failure is EINTR. This is flexible, but
usually inconvenient. Typically, POSIX applications that use signal
handlers must check for EINTR after each library function that can
return it, in order to try the call again. Often programmers forget to
check, which is a common source of error.
So you can handle the EINTR error, there is another choice by the way, You can use sigaction to establish a signal handler specifying how that handler should behave. Using the SA_RESTART flag, return from that handler will resume a primitive; otherwise, return from that handler will cause EINTR.
see interrupted primitives
this is my first post here. I'm asking because I ran out of clues and I was unable to find anything about this specific issue.
My question is: In Adobe AIR, is there a way to do a synchronous usleep() equivalent (delay execution of 200ms), alternatively is there a way to specify the SQLite busy timeout somewhere?
I have an AIR application which uses the database in synchronous mode because the code cannot cope with the need of events/callbacks in SQL queries.
The database sometimes is accessed from another application, such that it is busy. Hence the execute() of a statement throws SQLerror 3119 detail 2206. In this case the command shall be retried after a short delay.
As there is another application running on the computer I want to try to avoid busy waiting, however I'm stuck with it because of three things:
First, I was unable to find a way to give the SQLConnection a busy timeout value, like it is possible in C with the function sqlite3_busy_timeout()
Second, I was unable to find the equivalent of the C usleep() command in Adobe AIR / Actionscript.
Third, I am unable to use events/timers/callbacks etc. at this location. The SQL execute() must be synchronous because it is called from deeply nested classes and functions in zillion of places all around in the application.
If the application could cope with events/callbacks while doing SQL I would use an asynchronous database anyway, so this problem cannot be solved using events. The retry must be done on the lowest level without using the AIR event processing facility.
The lowest level of code looks like:
private static function retried(fn:Function):void {
var loops:int = 0;
for (;;) {
try {
fn();
if (loops)
trace("database available again, "+loops+" loops");
return;
} catch (e:Error) {
if (e is SQLError && e.errorID==3119) {
if (!loops)
trace("database locked, retrying");
loops++;
// Braindead AIR does not provide a synchronous sleep
// so we busy loop here
continue;
}
trace(e.getStackTrace());
trace(e);
throw e;
}
}
}
One sample use of this function is:
protected static function begin(conn:SQLConnection):void {
retried(function():void{
conn.begin(SQLTransactionLockType.EXCLUSIVE);
});
}
Output of this code is something like:
database locked, retrying
database available again, 5100 loops
Read: The application loops over 500 times a second. I would like to reduce this to 5 loops somehow to reduce CPU load while waiting, because the App shall run on Laptops while on battery.
Thanks.
-Tino