I need to run a cleanup before exiting service upon termination (by Linux systemctl stop my-srv
I came up so far with 2 solutions:
void signal_callback(int code)
{
_exit(0);
}
. . .
void main.. {
signal(SIGTERM, signal_callback)
fgetc(stdin); // wait for signal
}
on what thread the signal_callback is called? will it be the same thread which registered the callback? I mean if I call signal on main thread and then call exit in the signal_callback - will the application terminate gracefully?
on what thread the signal_callback is called?
Depends on how you send the signal.
If you send a signal using raise, then the callback will be called in the same thread.
If you send a signal using pthread_kill, then the signal callback will be called in the thread that whose id was passed to pthread_kill.
If you send a signal using kill then I think it's best to quote documentation:
POSIX.1 requires that if a process sends a signal to itself, and
the sending thread does not have the signal blocked, and no other
thread has it unblocked or is waiting for it in sigwait(3), at
least one unblocked signal must be delivered to the sending
thread before the kill() returns.
There will be differences if
if I ... call exit in the signal_callback - will the application terminate gracefully?
No, exit is not an async safe function. It's not OK to call it from a signal handler.
Regarding edit: _exit is async safe so you may call it. But it won't call registered cleanup functions, nor would the stack be unwound, so I wouldn't describe it as "graceful" as such.
P.S. main must return int.
By default, signals are sent to the process; not to any specific threads that process may have. If there are multiple threadss, which thread handles signal(s) isn't specified by standards.
You can of course mask the signals so that certain threads don't receive them
or that only a specific thread handles the signals. See pthread_sigmask for Linux.
if I call signal on main thread and then call exit in the signal_callback - will the application terminate gracefully?
What "gracefully" means depends on your program. If you setup a signal handler as you have, it'd simply exit upon receiving the signal. Whether that the process dies cleanly depends on what it was doing when it received signal such as whether any cleanup action is needed, resources need to be released (the ones not released automatically upon exit), etc.
Related
I am a little confused about how the kill(pid, signal) function works - I believe it is asynchronous, so the signal may not arrive until after a few more instructions have been executed. My question is, if you call kill(pid, signal) and then return in the next line (As seen below), are you guaranteed that the signal will be caught and handled before the program terminates, or is it possible to exit without handling the signal if we run "return 0" before the kill function finishes?
kill(pid, SIGUSR1);
return 0;
If a process sends a signal only to itself, and that signal is not blocked, and there are no other pending signals for that process, then the signal will be sent synchronously (that is, before kill() returns).
That's not enough of a guarantee to be 100% reliable, so you might prefer not to rely on it. Another process might happen to send a different signal at precisely the same time, for example; that is probably outside of your control.
If a process sends a signal to a different process, then there is no guarantee that it will be received before kill() returns. But it will be sent even if the signalling function terminates.
If more than one process will receive the signal, kill may return after the first signal is sent, which is not guaranteed to be the signalling process. Again, this might result in the process returning before the signal is received. Some platforms may offer additional guarantees.
Here's the Posix specification:
If the value of pid causes sig to be generated for the sending process, and if sig is not blocked for the calling thread and if no other thread has sig unblocked or is waiting in a sigwait() function for sig, either sig or at least one pending unblocked signal shall be delivered to the sending thread before kill() returns.
The thing is, I have detached threads created on my server which works in a thread-per-client way, so the function which accepts a client, creates another listener function (as a thread, and detaches it) waiting for another client to join.
Like the following in pseudo code:
Listen to client...
Accept Client Connection...
If client connection is Valid then
Create and detach a thread of the exact same function.
Else
Keep on listening...
I detach the threads only because afterwards, the thread who created a certain thread is handling a client, if that client leaves all clients that logged in after that client would be forced to log out (because there's a chain of threads):
//-> means creating a thread
Listening thread... Handling Client 1 -> Listening... Handling 2 -> Listening... Handling 3
and so on. So when client 1's thread will terminate, all of the others would do so.
That is why I cannot give up on detach (unless I'd create the threads in the main(), obviously, but that's not the architecture of the program).
Now, the problem occurs when someone exits without informing a thing, so the thread won't peacefully end. The only time I notice the fact that a client is not online is when recv() or send() are returning a negative value. When I notice that, I have to terminate the thread.
I tried doing so by using std::terminate() but I get an error window saying r6010 - abort() has been called.
How do I terminate that thread without all of the server crashing?
Would I be forced to change the architecture ?
The way to end a thread is to return from its thread procedure.
If you want the ending decision to be made from deep inside processing code, then throw an exception that is caught by the thread procedure. This has several huge benefits over pthread_exit:
Stack unwinding occurs, so dynamic allocations used by your processing code won't be leaked (if properly held in smart pointers), as well as any other cleanup performed in destructors (flushing file buffers, etc).
In the future if you want to add retry logic or anything like that, you can catch the exception. Conversely a call to pthread_exit is like a call to std::terminate or std::exit -- the current context ends unconditionally (although a handler can be installed via set_terminate, that handler cannot cancel the exit). Reusable code should never force an application-level exit.
I think you need to put test a variable in your client comms loop that signals a thread when to return:
class ClientComms
{
// set to true when you want the thread to stop
std::atomic_bool done;
public:
ClientComms(): done(false) {}
void operator()()
{
while(!done)
{
// communicate with client
}
}
};
There are a lot of Qt multi-threading tutorials out there that state that a QThread can be stopped safely using the following two lines.
qthread.quit(); // Cause the thread to cease.
qthread.wait(); // Wait until the thread actually stops to synchronize.
I have a lot of code doing this, and in most cases of stopping thread, I'll always set my own cancel flag and check it often during execution (as is the norm). Until now, I was thinking that calling quit would perhaps cause the thread to simply no longer execute any waiting signals (e.g. signals that are queued will no longer have their slots called) but still wait on the currently executing slot to finish.
But I'm wondering if I was right or if quit() actually stops the execution of the thread where it's at, for instance if something is unfinished, like a file descriptor hasn't been closed, it definitely should be, even though in most cases my worker objects will clean up those resources, I'd feel better if I knew exactly how quit works.
I'm asking this because QThread::quit() documentation says that it's "equivalent to calling QThread::exit(0)". I believe this means that the thread would immediately stop where it's at. But what would happen to the stackframe that quit was called in?
QThread::quit does nothing if the thread does not have an event loop or some code in the thread is blocking the event loop. So it will not necessarily stop the thread.
So QThread::quit tells the thread's event loop to exit. After calling it the thread will get finished as soon as the control returns to the event loop of the thread.
You will have to add some kind of abort flag if you are blocking event loop for example by working in a loop. This can be done by a boolean member variable that is public or at least has a public setter method. Then you can tell the thread to exit ASAP from outside (e.g. from your main thread) by setting the abort flag. Of course this will require your thread code to check the abort flag at regular intervals.
You may also force a thread to terminate right now via QThread::terminate(), but this is a very bad practice, because it may terminate the thread at an undefined position in its code, which means you may end up with resources never getting freed up and other nasty stuff. So use this only if you really can't get around it. From its documentation:
Warning: This function is dangerous and its use is discouraged. The thread can be terminated at any point in its code path. Threads can be terminated while modifying data. There is no chance for the thread to clean up after itself, unlock any held mutexes, etc. In short, use this function only if absolutely necessary.
I think this is a good way to finish a thread when you are using loops in a thread:
myThread->m_abort = true; //Tell the thread to abort
if(!myThread->wait(5000)) //Wait until it actually has terminated (max. 5 sec)
{
myThread->terminate(); //Thread didn't exit in time, probably deadlocked, terminate it!
myThread->wait(); //We have to wait again here!
}
In case, if you want to use Qt's builtin facility then try QThread::requestInterruption().
Main thread
struct X {
QThread m_Thread;
void Quit ()
{
m_Thread.quit();
m_Thread.requestInterruption();
}
};
Some Thread referred by X::m_Thread
while(<condition>) {
if(QThread::currentThread()->isInterruptionRequested())
return;
...
}
As per the documentation:
void QThread::requestInterruption()
Request the interruption of the thread. That request is advisory and it is up to code running on the thread to decide if and how it should act upon such request. This function does not stop any event loop running on the thread and does not terminate it in any way.
I have stumbled upon this problem, as others haves:
QThread won't stop / does not process a signal
QThread - Using a slot quit() to exit the thread
The problem is that I want to have a worker thread started, do some job (which involves sending signals to other threads in my code, and receiving signals asynchronously) and then exit. But I want this thread to be synchronized with the code that is starting it. In other words, I want the execution in the code which creates the worker thread to be halted until the worker thread is done its job.
But it seems this is not possible in Qt. The reason is that the worker's QThread.quit() slot cannot be signaled from within the thread itself. The event loop which listens for signals to this slot, should reside in the same thread that created the worker thread. This means the creating thread should not be blocked, otherwise the worker thread never stops.
Which brings me to my question, that what is the point of QThread.wait() then? I think this function should just be stuck at the end of the program to make sure all the threads have exited, but it cannot actually be used to synchronize threads, at least it cannot be used to synchronize a worker thread, with the thread that created it. Because if the QThread.wait() is called from the creating thread, it blocks its event loop, which will block the worker thread's interface, which will prevent it from ever exiting.
Am I missing something?
I thought I need to add a code snippet:
for (auto i = myVector.begin(); i < myVector.end(); ++i)
{
// 5-line best practice creation for the thread
QThread* workerThread = new QThread;
MyWorkerObject* workerObject = new MyWorkerObject(0);
workerObject->moveToThread(workerThread);
QObject::connect(workerThread, SIGNAL(started()), workerObject, SLOT(init()));
QObject::connect(workerThread, SIGNAL(finished()), workerObject, SLOT(deleteLater()));
// Stop mechanism
QObject::connect(workerObject, SIGNAL(finished()), workerThread, SLOT(quit()));
// Start mechanism
wokerThread->start();
// Invoking the work
QMetaObject::invokeMethod(workerObject, "StartYourJob", Qt::QueuedConnection, Q_ARG(SomeType, *i));
// Synchronization
workerThread->wait();
delete wokerThread;
}
I finally found my answer here:
http://comments.gmane.org/gmane.comp.lib.qt.user/6090
In short, if QThread::quit() is invoked as a slot, the event loop handler of the creating thread will deal with it, which is not what I want.
I should call it directly. So when the workerObject finishes its job, instead of sending a signal (which has to pass through the blocked creating thread), it should directly call its container's quit:
this->thread()->quit();
This would be the exit point of the workerObject. Now there is no need for the stop mechanism and these lines can be eliminated from the code.
// Stop mechanism
QObject::connect(workerObject, SIGNAL(finished()), workerThread, SLOT(quit()));
Does anybody see any problem with this approach?
The purpose of threads is to allow processes to run concurrently (at the same time!), so if you're just creating a thread to do work and waiting on the current thread, you don't need to be using a new thread.
To answer your question of the purpose of QThread::wait(), the Qt documentation states that it is similar to the POSIX function pthread_join. A quick search on pthread_join reveals this link, which states the rationale is as follows: -
The pthread_join() function is a convenience that has proven useful in
multi-threaded applications. It is true that a programmer could
simulate this function if it were not provided by passing extra state
as part of the argument to the start_routine(). The terminating thread
would set a flag to indicate termination and broadcast a condition
that is part of that state; a joining thread would wait on that
condition variable. While such a technique would allow a thread to
wait on more complex conditions (for example, waiting for multiple
threads to terminate), waiting on individual thread termination is
considered widely useful. Also, including the pthread_join() function
in no way precludes a programmer from coding such complex waits. Thus,
while not a primitive, including pthread_join() in this volume of
POSIX.1-2008 was considered valuable.
The pthread_join() function provides a simple mechanism allowing an
application to wait for a thread to terminate. After the thread
terminates, the application may then choose to clean up resources that
were used by the thread. For instance, after pthread_join() returns,
any application-provided stack storage could be reclaimed.
The pthread_join() or pthread_detach() function should eventually be
called for every thread that is created with the detachstate attribute
set to PTHREAD_CREATE_JOINABLE so that storage associated with the
thread may be reclaimed.
The interaction between pthread_join() and cancellation is
well-defined for the following reasons:
The pthread_join() function, like all other non-async-cancel-safe
functions, can only be called with deferred cancelability type.
Cancellation cannot occur in the disabled cancelability state.
Thus, only the default cancelability state need be considered. As
specified, either the pthread_join() call is canceled, or it succeeds,
but not both. The difference is obvious to the application, since
either a cancellation handler is run or pthread_join() returns. There
are no race conditions since pthread_join() was called in the deferred
cancelability state.
If an implementation detects that the value specified by the thread
argument to pthread_join() does not refer to a joinable thread, it is
recommended that the function should fail and report an [EINVAL]
error.
If an implementation detects that the value specified by the thread
argument to pthread_join() refers to the calling thread, it is
recommended that the function should fail and report an [EDEADLK]
error.
If an implementation detects use of a thread ID after the end of its
lifetime, it is recommended that the function should fail and report
an [ESRCH] error.
QThread::wait() is not what you need. This function is exactly what you mentioned, it waits for thread termination.
bool QThread::wait ( unsigned long time = ULONG_MAX )
Blocks the thread until either of these conditions is met:
The thread associated with this QThread object has finished execution (i.e. when it
returns from run()). This function will return true if the thread has finished. It also
returns true if the thread has not been started yet.
time milliseconds has elapsed. If time is ULONG_MAX (the default), then the wait will
never timeout (the thread must return from run()). This function will return false if the
wait timed out.
If you need to synchronize two threads (Your main thread and created thread) then I recommend using signals and slots to signal which one is ready (trigger a isReady bool) and have a while (!isReady) { sleep(1ms); processEvents(); } loop going. May not be the best way but should work.
I have a main(), which spawns a thread, and then joins to it.
I want to be able to CTRL-C the program, so I would install SIGINT handler in main (the spawn thread will ignore this signal). When I am in sig-handler I will cancel the spawned thread with cancel(), but what happens with the current 'join()', which was active during the signal invocation.
My guess is that I will get EAGAIN or EINTR, and I would have to make join() in loop. Am I right? Thank you.
The question is: Is this legal with mulithreading. I don't mind to just set a flag withing SIGINT handle, but what happens with the join() call?
Signals and threads? Here be dragons! You have to fully-specify the masks, or else any thread may receive the signal.
The signal handler should generally not assume it is running in the "main" thread. Rather, it should post a message and return, analagously to thread interruption. The main thread can pick this up later in an event loop or whatever and then join.
std::thread::join() has a void return type, so cannot return EINTR. On POSIX platforms it is likely a wrapper around pthread_join, which does not return EINTR. Joining a thread should not return or throw until the thread has been successfully joined-with, provided it is called on a joinable thread.
As an aside, it may not be safe to cancel the thread from a signal handler. std::thread does not have a cancel() member function, so I presume you have written your own. You therefore need to check that it is safe for use in a signal handler --- pthread_cancel() is not listed as a function that is safe to call from a signal handler, for example.