Application does not exit on logout - c++

I would like to ask what is the signal that is called when the user logs out? I have a Qt gui app that has handler for SIGTERM and SIGHUP signals. The app also has its own close event handler, so user can't close it by clicking on "X". The problem is that when the user logs out then the ubuntu hangs (the icon from taskbar disappears but the process keeps running) and does not let the user log out because (imo) it waits for the process to be terminated. When I use kill -15 'myapp' command then the app closes normally as it is supposed to so the problem shouldn't be in my handler.
static int setupHandlers(){
struct sigaction hup,term;
hup.sa_handler = signalHandler;
sigemptyset(&hup.sa_mask);
hup.sa_flags = 0;
if (sigaction(SIGHUP, &hup, 0) > 0){
return 1;
}
term.sa_handler = signalHandler;
sigemptyset(&term.sa_mask);
if (sigaction(SIGTERM, &term, 0) > 0){
return 2;
}
return 0;
}
signalHandler just calls exit(0) (also tried _exit(0) and abort())

There are 3 standart terminating signals, that you can handle - SIGINT, SIGQUIT and SIGTERM. Try to subscribe to each one of them and look.

signalHandler just calls exit(0) (also tried _exit(0) and abort())
You rather need to tell Qt to exit. Your signal handler need to have a reference on the application object and call QCoreApplication::exit(0);.
Whether it is by SIGTERM or by the user user input, your application need to nicely handle termination requests. In particular ensure that all objects which launch a process or a thread are cleanly destroyed when it happens. The classic code inspired from QtCreator :
d->m_guiProcess.terminate();
if (!d->m_guiProcess.waitForFinished(1000)) { // This is blocking, so be fast.
d->m_guiProcess.kill();
d->m_guiProcess.waitForFinished();
}
The code executing this need to stop, so it first forward nicely a SIGTERM (terminate), wait for small amount of time and then ask rudely with a SIGKILL (kill).

Related

Is there a workaround for SetConsoleCtrlHandler() issue?

Windows 10, C++. I have a graphic app which opens a console, writes a few things, and waits until user clicks the close on the console. I only want for console to close, but the entire app exits. Yes, the handler is entered. I also see that this was an issue more than 10 years ago. So, is there another way around this?
// Graphic app makes following calls
...
AllocConsole();
SetConsoleCtrlHandler(ConsoleCloseHandler, TRUE);
...
The handler is defined as follows.
BOOL WINAPI ConsoleCloseHandler(DWORD signalType) {
switch (signalType) {
case CTRL_CLOSE_EVENT:
case CTRL_C_EVENT:
FreeConsole();
return TRUE;
default: return FALSE;
}
}
No matter which value your handler returns, Windows is going to kill your process after your or the last handler returns.
If your process is going to shut down soon after receiving this signal, notify your application to start shutting down and then sleep/wait forever in the handler.
If you want your application to continue to run as normal, you could perhaps call ExitThread(1337); in your handler. This is a giant hack and who knows if it works on all Windows versions.
If neither of the two methods are acceptable then I'm afraid you might have to use a child process as the console owner.

wxWidgets C++ console application: how to capture INT/TERM signals?

I have a wxWidgets console application, and I need to handle SIGINT / SIGTERM signals to shutdown program properly.
I've tried "classic" signals handling, but it does not works:
#include <signal.h>
bool MainApp::OnInit()
{ // terminate gracefully:
// term threads, wait them for terminate, etc.
}
static void OnSignal(int sig)
{ // captured signal:
cout<<"Terminating...\r\n";
wxGetApp().OnExit();
}
bool MainApp::OnInit()
{
// init app here, create working threads, etc.
// set own handler:
cout<<"Signal set handler result: "<<signal(SIGINT,OnSignal);// returns 0
return true;// app inited successfully
}
When I send SIGINT or SIGTERM signals (using integrated CodeLite's terminal for debugging), nothing happens.
Looks like wxWidgets still does not have signal processing - at least, I've found nothing in documentation.
The question is: how to capture INT/TERM signals? (At least in Linux, but cross-platform solution is of course better).
You can't use cout nor exit the application from a signal handler, so while I don't know why it isn't called at all for you, things would only be worse, not better, if it was.
wxWidgets has private (i.e. undocumented, liable to change) wxApp::SetSignalHandler() in Unix ports which implements proper signal handling, with the handler itself just waking up the event loop and telling it to wait for the signals. If you do anything other than just setting a flag in your signal handler, this is what you should do as well.

run background process linux simple shell. C++

I'm creating a simple shell in linux and I'm having trouble getting a command to run in the background.
here is my code so far:
create command,argv and check if it is to be ran in the background &
enter this code:
if(strcmp(command,"cd")==0)
{
chdir(argv[1]);
}
else if(strcmp(command,"clr") == 0)
{
if ((pid = fork()) == 0)
{
execvp("clear",argv);
}
wait(&status);
}
else
{
if ((pid = fork()) == 0)
{
execvp( prog, argv );
}
wait(&status);
}
command and argv are what I get from the user.
I need to run a command in the background if '&' is the last part of the command. I have already checked for that with a boolean var of bg. but I'm having trouble with the WAITPID() function im not sure where it goes.
I guess your issue is if you end up calling waitpid() directly, you will block, and the process is not really running in the background. You can handle this in two ways.
Choice 1: Avoid the issue. After calling fork once, have the child fork one more time. Let the grandchild execute the command, and let the child exit. The parent waits on the child like before, but the grandchild is executing the command in the background. The grandchild process will be reaped by the init process.
Choice 2: Notice the asynchronous notification that the child is done. When a child process dies, the parent process will receive the SIGCHLD signal. Have a signal handler notice this signal and reap the child. This might require that you restructure your code so that the synchronous waiters actually receive a synchronous notification from your signal handler. You would then need a mechanism for the signal handler to distinguish between foreground and background children, and only send synchronous notifications for the foreground children.

Application crashes on dialogue close with threads running

In my application I have a modal dialog which contains about 20 different combo boxes which are bind to certain fields in the databases. The database is huge and on the loading of dialog I have to load all the combo boxes from the databases. So I setup 20 threads (1 each for every combo box).
Everything works fine, but the problem only occurs when the user closes the dialog with close or cancel button or OK button while the threads are running; in that case the application crashes.
I have tried to terminate the threads prematurely as well but that does not help. Here is the thread termination code
if(m_iNoOfThreadsCompleted != m_iTotalThreads)
{
for(int i = 0; i < m_iTotalThreads - 1; i++)
{
if (m_threads[i] != NULL)
{
GetExitCodeThread(m_threads[i]->m_hThread, &exit_code);
if(exit_code == STILL_ACTIVE)
CloseHandle(m_threads[i]->m_hThread);
}
if(m_iNoOfThreadsCompleted == m_iTotalThreads)
break;
}
}
What is the issue? Or do I need to use a better approach?
Synchronizing threads is generally done using events.
// Before Creating threads
HANDLE hEndEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
// Pass handle to threads
Then on termination
SetEvent(hEndEvent);
WaitForMultipleObjects(m_iTotalThreads,m_threads,TRUE,INFINITE); // Wait for all threads to end
// Loop through and close all the thread handles
Note that you need to be occasionally looking for the end event to be set otherwise your threads won't end.
// In Thread
if (WaitForSingleObject(hEndEvent,0)==WAIT_OBJECT_0) {
// Clean up
return 0;
}
CloseHandle does not terminate the thread. You can call TerminateThread but it's not the nicest thing to do...
What is normal is to provide your threads with a manual-reset event object that signals a shutdown is taking place. Sometimes it's also good to have a flag so that threads can abort lenghty operations. The threads carry on their work as usual, and whenever they have to wait on some object, you include the shutdown event object in that wait.
So the procedure on exit is normally to do this:
Set the shutdown flag
Signal the shutdown event
Resume all threads (in case any are suspended)
WaitForMultipleObjects on all thread handles, with an appropriate timeout
Call TerminateThread on any threads that did not exit within the timeout
Close all thread handles
Destroy the shutdown event
This approach requires that threads are created with _beginthreadex, so that you are responsible for closing the handles. The benefit of this is that you can wait on threads, even after they've exited (of course an exited thread is already in the signaled state).
As an alternative to what paddy describes another approach would be to instead of having 20 threads that load the comboboxes to just have one thread that loads. By having 20 threads you may not be speeding up things anyway depending on your database library.
Then when that thread is loading periodically (like between each checkbox) check whether user pressed cancel or not, if so then stop processing and exit the thread.
This would make the handling less complicated than managing 20 threads IMHO.

send SIGINT to child process

I am trying to create a child process and then send SIGINT to the child without terminating the parent. I tried this:
pid=fork();
if (!pid)
{
setpgrp();
cout<<"waiting...\n";
while(1);
}
else
{
cout<<"parent";
wait(NULL);
}
but when I hit C-c both process were terminated
Don't use CTRL-C, this sends a signal to all processes with the same controlling terminal (ie, in the same session). That's something that setpgid doesn't change though I think there's a setsid (set session ID) call for that purpose.
The easiest solution is simply to target the specific process rather than a session. From the command line:
kill -INT pid
From C:
kill (pid, SIGINT);
where pid is the process ID you want to send the signal to.
The parent can get the relevant PID from the return value from fork(). If a child wants its own PID, it can call getpid().
Aha, the mystery of process groups and sessions and process group leaders and session group leaders appears again.
Your control/C sent the signal to a group. You need to signal an individual pid, so follow paxdiablo's instructions or signal ("kill") the child from the parent. And don't busy wait! Put a sleep(1) in the loop, or better yet, one of the wait(2) system calls.
You could try implementing a SIGINT signal handler which, if a child process is running, kills the child process (and if not, shuts down the application).
Alternatively, set the parent's SIGINT handler to SIG_IGN and the child's to SIG_DFL.