Confusion about CTRL_SHUTDOWN_EVENT handling in DLLs and WM_QUERYENDSESSION - c

My UI is in a DLL. Right now, both the DLL and the EXE that uses it are compiled as console programs so I can use stdout and stderr for debugging and error reporting during development. One of the things is that I have an uninit() function that makes sure the DLL isn't leaking memory.
As a result, I have a control handler set up by the DLL such that CTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT simulate the user clicking the Quit option from the File menu: it does PostQuitMessage(0), with the cleanup code happening after the message pump returns.
I know that normally CTRL_SHUTDOWN_EVENT cannot be ignored, and that the program will terminate after the handler routine returns, regardless of what it returns. But according to MSDN,
Note that a third-party library or DLL can install a console control handler for your application. If it does, this handler overrides the default handler, and can cause the application to exit when the user logs off.
If I am reading this correctly, this says that a control handler that is installed by a DLL overrides the handler that causes my program to quit when the handler function returns. Am I wrong about that? My DLL's handler function simply returns TRUE, which I assume will further stop any other defaults from running given the blurb above.
Why? I'm noticing weird behavior:
On Windows Vista, the program closes regardless of what I do. In this case, I'm wondering if the blurb is wrong and that the handler that terminates the process is still running. This happens regardless of whether I have called ShutdownBlockReasonCreate().
On Windows 7, however, it seems that my program's main window gets a WM_QUERYENDSESSION, and Windows responds to it accordingly. That means that if I say "no, don't quit yet (don't call PostQuitMessage(0))" in my Quit function, Windows pops up the "an application is preventing shutdown" screen saying my main window is preventing shutdown. In that case, the blurb above appears to be correct, as the program is not quitting on return from the console handler (if it's even being called!).
If I instead say "yes, call PostQuitMessage(0), the program quits normally. However, I lose the debugging output on stdout and stderr, so I can't tell if it really is quitting normally or not. Invoking my program as
new.exe > out.txt 2> err.txt
on cmd.exe produces two empty files; I don't know why the output isn't saving on system shutdown (and Googling doesn't turn up any information).
So can someone help clear up my confusion so I can implement this (including ShutdownBlockReasonCreate()) properly? Thanks.

When you return TRUE from the handler you registered, Windows immediately terminates the process. When you return FALSE, the previous handler gets called. Ultimately that will be the default handler, it immediately terminates the process.
So what you have to do is not return and block until you are happy. That requires synching with the thread that's pumping the message loop. You'd use an event, the pumping thread can call SetEvent() after its message loop and your handler can call WaitForSingleEvent() to block after it called PostQuitMessage().
It is however a threading race, your UI thread was probably started by main() and the CRT is going to terminate the program when main() returns. Which one will get there first is a unpredictable.
Having the feeling you are doing something wrong? Well, you are. A console window just isn't a very good way to display debug output. Not sure why you are doing this but I know your tool-chain is unusual, I can never get any of your code snippets to compile and run. The proper way is OutputDebugString(). That function talks to your debugger and gets it to display text. Even if your debugger isn't capable of displaying such text, you can still fallback to SysInternals' DebugView utility.
Your are probably using printf() and won't enjoy fixing all your debug statements, simply write your own version of that links ahead of the CRT, use vprintf() and OutputDebugStringA().

Related

How to exit console screen in C language

I'm trying to exit the console screen i.e close the screen what command can i use to achieve this.
void main()
{
int n;
printf("Please enter a number less than 5");
scanf("%d", &n);
if(n <= 5)
printf("good");
else
{
printf("You entered a number above so the program will exit");
//here i need to call a function or use a command that will close
// the console screen;
}
}
Any help will be appreciated thanks
The C11 standard n1570 does not know about the "console screen" (and I guess you speak of the terminal emulator running your program). Notice that C11 does not mention "screens" or "keyboards" (only standard streams, and very often stdout is not a "console") and many computers (e.g. most Internet servers or supercomputers, or even your mobile phone...) don't have both. Also, your program could be run (even on Windows) with redirections or in a pipeline and then it has no console (so your question don't make any sense in such a common case).
So in general, there is no way to do what you want (since it does not make any sense), in a standard way.
Perhaps your operating system provide some (OS specific) way to achieve that. So investigate the OS API relevant to your system (e.g. WinAPI on Windows, or Linux syscalls -listed in syscalls(2)).
Perhaps you want to use some terminal related library like ncurses.
If your terminal follows the ANSI escape code conventions, you might follow them.
Otherwise, consider making your program having some GUI. For that, you practically need some widget toolkit (such as Qt, GTK, etc..)
You might also consider some inter-process communication with your desktop environment. How to do that (or even its possibility) is very operating-system and desktop specific and might be related to session management.
BTW, remember that stdout is often buffered (and perhaps line-buffered). You'll better end your printf control strings with \n and/or call fflush.
In a windowing operating system or execution environment the console window will close immediately the process terminates, so it is not clear what you are asking here since in your example the program terminates regardless of what input is entered.
If you are running the code from an IDE, often the IDE will create a console process and launch your code within that. In that case the console is not "owned" by your application, but is executed as a child process; in which case the window will remain open until the parent process launched by the IDE is closed. Similarly if you launch your program from a command shell. It is probably unreasonable behaviour for a process to attempt to close its parent even if it is possible.
It is possible to "hide" the console window while the process continues to run, which may be what you are asking; the means of doing that is platform specific, and you have not specified; for Windows such a question would be a duplicate of Win32 programming hiding console window. However it is quite possible that these methods will not work if the process is not launched directly but from some other console process.
in Windows you may simply write code on Notepad, then compile and run it through the Command prompt (cmd.exe). If you have GCC installed as compiler (with all the needed packages), then compile your main.c file as:
gcc main.c -o main.exe
If all went fine, as you run "main", there will be all of your output that you can close or step over for more editing. Bye
PS EDIT -- I see your point: when you launch your .exe from itself, the window closes without giving satisfaction of the messages. You may add a workaround like this before the last curly bracket:
printf("Press any key\n");
scanf("%d");
}
So the output window will still wait for one more input before closing.
You may check for additional information for eg here: https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
Bye

Prevent glibc from showing extra abort information [duplicate]

Some C++ libraries call abort() function in the case of error (for example, SDL). No helpful debug information is provided in this case. It is not possible to catch abort call and to write some diagnostics log output. I would like to override this behaviour globally without rewriting/rebuilding these libraries. I would like to throw exception and handle it. Is it possible?
Note that abort raises the SIGABRT signal, as if it called raise(SIGABRT). You can install a signal handler that gets called in this situation, like so:
#include <signal.h>
extern "C" void my_function_to_handle_aborts(int signal_number)
{
/*Your code goes here. You can output debugging info.
If you return from this function, and it was called
because abort() was called, your program will exit or crash anyway
(with a dialog box on Windows).
*/
}
/*Do this early in your program's initialization */
signal(SIGABRT, &my_function_to_handle_aborts);
If you can't prevent the abort calls (say, they're due to bugs that creep in despite your best intentions), this might allow you to collect some more debugging information. This is portable ANSI C, so it works on Unix and Windows, and other platforms too, though what you do in the abort handler will often not be portable. Note that this handler is also called when an assert fails, or even by other runtime functions - say, if malloc detects heap corruption. So your program might be in a crazy state during that handler. You shouldn't allocate memory - use static buffers if possible. Just do the bare minimum to collect the information you need, get an error message to the user, and quit.
Certain platforms may allow their abort functions to be customized further. For example, on Windows, Visual C++ has a function _set_abort_behavior that lets you choose whether or not a message is displayed to the user, and whether crash dumps are collected.
According to the man page on Linux, abort() generates a SIGABRT to the process that can be caught by a signal handler. EDIT: Ben's confirmed this is possible on Windows too - see his comment below.
You could try writing your own and get the linker to call yours in place of std::abort. I'm not sure if it is possible however.

gtk/c manipulate GUI in a thread: strange errors

I wrote a C/S application using udp and it keeps giving me errors, which I believe has something to do with the way I use threads.
When the client program starts, it first initializes a login window and starts a new thread to listen to the response from the server. After it submits user name and password, the new thread will receive a message indicating whether it submitted the right info. If it did, then the thread would initializes the main GUI window. But it would give strange errors:
Fatal IO error 11 (Resource temporarily unavailable) on X server :0.0
or
python: Fatal IO error 0 (Success) on X server :0.0
I found a similar question here, but it's not solved.
Some say GUI should only be manipulated in the main thread, but others say it's not true.
I also tried using gdk_threads_enter() and gdk_threads_enter() around gtk_main() and the code where I initialize window in that listen thread. But it didn't seem to work.
I don't know much about threads so be patient when pointing out where I have done wrong.
Thanks.
These error messages, I have found, pop up from time to time when you are not holding the GTK lock properly.
You should put gdk_threads_enter() and gdk_threads_leave() around the original gtk_main() call, and also around every call to a GTK function that takes place
outside the thread from which you called gtk_main()
but not in a signal, idle, or timeout handler.
This usage is on its way out though as I understand, and in future versions of GTK it will only be possible to manipulate GTK from the main thread.
It is true that GTK windows should only be manipulated from the main thread.
That said, in some architectures (notably GNU/Linux) you can manipulate GTK windows from another thread provided that you properly use the global lock with gdk_threads_enter() / gdk_threads_leave(). The key word is "properly", that's not as easy as it seems.
And that said, in some architectures (notably MS-Windows) doing that may seem to work in some simple programs, but will fail miserably in more complex ones.
About your question, you don't say it, but you seem to be using Python somewhere, but you don't say where... Mixing Python and native threads is probably not such a good idea, either.

Preventing MSYS 'bash' from killing processes that trap ^C

I have a console-mode Windows application (ported from Unix) that was originally designed to do a clean exit when it received ^C (Unix SIGINT). A clean exit in this case involves waiting, potentially quite a long time, for remote network connections to close down. (I know this is not the normal behavior of ^C but I am not in a position to change it.) The program is single-threaded.
I can trap ^C with either signal(SIGINT) (as under Unix) or with SetConsoleCtrlHandler. Either works correctly when the program is run under CMD.EXE. However, if I use the "bash" shell that comes with MSYS (I am using the MinGW environment to build the program, as this allows me to reuse the Unix makefiles) then the program is forcibly terminated some random, short time (less than 100 milliseconds) after the ^C. This is unacceptable, since as I mentioned, the program needs to wait for remote network connections to close down.
It is very likely that people will want to run this program under MSYS bash. Also, this effect breaks the test suite. I have not been able to find any way to work around the problem either from within the program (ideal) or by settings on the shell (acceptable). Can anyone recommend anything?
I had the exact same problem - I had written a program with a SIGINT/SIGTERM handler. That handler did clean-up work which sometimes took awhile. When I ran the program from within msys bash, ctrl-c would cause my SIGINT handler to fire, but it would not finish - the program was terminated ("from the outside", as it were) before it could complete its clean-up work.
Building on phs's answer, and this answer to a similar question: https://stackoverflow.com/a/23678996/2494650, I came up with the following solution. It's insanely simple, and it might have some side-effects that I've yet to discover, but it fixed the problem for me.
Create a ~/.bashrc file with the following line:
trap '' SIGINT
That's it. This traps the sigint signal and prevents msys bash from terminating your program "from the outside". However, it somehow still lets the SIGINT signal through to your program, allowing it to do its graceful cleanup/shutdown. I can't tell you exactly why it works this way, but it does - at least for me.
Good luck!
This could be due to the infamous mintty "Input/Output interaction with alien programs" problem (aka mintty issue #56). In this case it is manifesting as Ctrl-C abruptly killing the program rather than being passed down to the program as a signal to be caught and handled. Evidence for this theory is based on zwol's extensive explanation: "console-mode Windows application", "[application is] designed to do a clean exit when it received ^C", "[application] works correctly when the program is run under CMD.EXE" but "[when using the terminal] that comes with MSYS [...] program is forcibly terminated" (at the time of writing (2018) MSYS defaults to using mintty as its terminal).
Unfortunately mintty isn't a full Windows console replacement and various behaviours expected by "native" Windows programs are not implemented. However, you might have some joy wrapping such native programs in winpty when running them within mintty...
Other questions also describe this behaviour: see https://superuser.com/questions/606201/how-to-politely-kill-windows-process-from-cygwin and https://superuser.com/questions/1039098/how-to-make-mintty-close-gracefully-on-ctrl-c .
Arg - 5 minute edit on comment. Here's what I wanted to write:
As a workaround, instead of trying to trap the CTRL-C event which is also being propagated to the shell I'd propose turning off the ENABLED_PROCESSED_INPUT on stdin so that CTRL-C is reported as a keyboard input instead of as a signal:
DWORD mode;
HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode(hstdin, &mode);
SetConsoleMode(hstdin, mode & ~ENABLE_PROCESSED_INPUT); /* disable CTRL-C processing as a signal */
You could then process keyboard input in your main thread while the rest of the program does its thing in a separate thread and set an event to cleanup when CTRL-C is received.
When you run your program with MSYS bash, do you run the executable directly, or is there a wrapping (bash) shell script?
If so, it may be registering a custom Ctrl-C handler with the trap command (that does a sleep followed by a kill.) If such a thing exists, alter or remove it.
If there is no trap registered, or there is no wrapping script, consider making such a script and adding your own trap to override the default behavior. You can see an example of how to use it here or on bash's man page (in the SHELL BUILTINS section).
Ctrl-C is SIGINT? I thought Ctrl-Z was SIGINT, but Ctrl-C is SIGTERM. Check that.
Do you have a CYGWIN environment setting (in control panel/environment variables)? Try setting CYGWIN=notty and restart open a new MSYS bash shell - does the problem persist?

detect program termination (C, Windows)

I have a program that has to perform certain tasks before it finishes. The problem is that sometimes the program crashes with an exception (like database cannot be reached, etc).
Now, is there any way to detect an abnormal termination and execute some code before it dies?
Thanks.
code is appreciated.
1. Win32
The Win32 API contains a way to do this via the SetUnhandledExceptionFilter function, as follows:
LONG myFunc(LPEXCEPTION_POINTERS p)
{
printf("Exception!!!\n");
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)&myFunc);
// generate an exception !
int x = 0;
int y = 1/x;
return 0;
}
2. POSIX/Linux
I usually do this via the signal() function and then handle the SIGSEGV signal appropriately. You can also handle the SIGTERM signal and SIGINT, but not SIGKILL (by design). You can use strace() to get a backtrace to see what caused the signal.
There are sysinternals forum threads about protecting against end-process attempts by hooking NT Internals, but what you really want is either a watchdog or peer process (reasonable approach) or some method of intercepting catastrophic events (pretty dicey).
Edit: There are reasons why they make this difficult, but it's possible to intercept or block attempts to kill your process. I know you're just trying to clean up before exiting, but as soon as someone releases a process that can't be immediately killed, someone will ask for a method to kill it immediately, and so on. Anyhow, to go down this road, see above linked thread and search some keywords you find in there for more. hook OR filter NtTerminateProcess etc. We're talking about kernel code, device drivers, anti-virus, security, malware, rootkit stuff here. Some books to help in this area are Windows NT/2000 Native API, Undocumented Windows 2000 Secrets: A Programmer's Cookbook, Rootkits: Subverting the Windows Kernel, and, of course, Windows® Internals: Fifth Edition. This stuff is not too tough to code, but pretty touchy to get just right, and you may be introducing unexpected side-effects.
Perhaps Application Recovery and Restart Functions could be of use? Supported by Vista and Server 2008 and above.
ApplicationRecoveryCallback Callback Function Application-defined callback function used to save data and application state information in the event the application encounters an unhandled exception or becomes unresponsive.
On using SetUnhandledExceptionFilter, MSDN Social discussion advises that to make this work reliably, patching that method in-memory is the only way to be sure your filter gets called. Advises to instead wrap with __try/__except. Regardless, there is some sample code and discussion of filtering calls to SetUnhandledExceptionFilter in the article "SetUnhandledExceptionFilter" and VC8.
Also, see Windows SEH Revisited at The Awesome Factor for some sample code of AddVectoredExceptionHandler.
It depends what do you do with your "exceptions". If you handle them properly and exit from program, you can register you function to be called on exit, using atexit().
It won't work in case of real abnormal termination, like segfault.
Don't know about Windows, but on POSIX-compliant OS you can install signal handler that will catch different signals and do something about it. Of course you cannot catch SIGKILL and SIGSTOP.
Signal API is part of ANSI C since C89 so probably Windows supports it. See signal() syscall for details.
If it's Windows-only, then you can use SEH (SetUnhandledExceptionFilter), or VEH (AddVectoredExceptionHandler, but it's only for XP/2003 and up)
Sorry, not a windows programmer. But maybe
_onexit()
Registers a function to be called when program terminates.
http://msdn.microsoft.com/en-us/library/aa298513%28VS.60%29.aspx
First, though this is fairly obvious: You can never have a completely robust solution -- someone can always just hit the power cable to terminate your process. So you need a compromise, and you need to carefully lay out the details of that compromise.
One of the more robust solutions is putting the relevant code in a wrapper program. The wrapper program invokes your "real" program, waits for its process to terminate, and then -- unless your "real" program specifically signals that it has completed normally -- runs the cleanup code. This is fairly common for things like test harnesses, where the test program is likely to crash or abort or otherwise die in unexpected ways.
That still gives you the difficulty of what happens if someone does a TerminateProcess on your wrapper function, if that's something you need to worry about. If necessary, you could get around that by setting it up as a service in Windows and using the operating system's features to restart it if it dies. (This just changes things a little; someone could still just stop the service.) At this point, you probably are at a point where you need to signal successful completion by something persistent like creating a file.
I published an article at ddj.com about "post mortem debugging" some years ago.
It includes sources for windows and unix/linux to detect abnormal termination. By my experience though, a windows handler installed using SetUnhandledExceptionFilter is not always called. In many cases it is called, but I receive quite a few log files from customers that do not include a report from the installed handlers, where i.e. an ACCESS VIOLATION was the cause.
http://www.ddj.com/development-tools/185300443

Resources