C++: How do I check if my window is about to close? - c++

I'm trying to make a Win32/*nix console-based ASCII game. I want to use no libraries whatsoever that aren't standard C++ or on *nix/windows(.h).
I want it to be structured like a game loop. Aka:
while (!WIN_CLOSE_FUNCTION()) {
//Do crap
}
//Do other shutdown crap
return 0;
Can anyone point me to what function this would be? If it is platform dependent, give me one example on Windows and *nix.

For the Unix/Linux console, there is no such function. The closest you can do is to catch the signal SIGHUP which is sent when losing the terminal. However be aware that the things you can do in a signal handler are quite limited. Probably the closest to your loop would be (note: untested code):
#include <signal.h>
volatile sig_atomic_t hupflag = 0;
extern "C" void hangup(int)
{
hupflag = 1;
}
int main()
{
sigaction act;
act.sa_handler = hangup;
act.sa_mask = 0;
act.sa_flags = 0;
if (sigaction(SIGHUP, &act, 0) < 0)
{
std::cerr << "could not install signal handler\n";
return 1;
}
while (!hupflag)
{
// ...
}
// shutdown
return 0;
}

Similar question that might help you What happens when you close a c++ console application
The accepted answer is:
Closing a c++ console app with the "x" in the top corner throws an CTRL_CLOSE_EVENT which you could catch and process if you set a control handler using the SetConsoleCtrlHandler function.
Useful links:
Console Event Handling
SetConsoleCtrlHandler
On *nix:
On Linux and other Unix systems, the console runs as a separate process. As you close the shell, it sends the SIGHUP signal to the currently active process or processes that are not executed in the background. If the programmer does not handle it, the process simply terminates. The same signal is sent if you close the SSH session with a terminal and an active process.
answer provided by #Zyx in the question linked above

There isn't such a function per se, but both Unix and Windows will send
a signal (SIGHUP under Unix, SIGBREAK under Windows) to all
processes in the process group when the window on which the process
group depends is closed. So all you have to do is catch the signal and
set a flag, which you test in the loop:
#ifdef _WIN32
int const sigClosed = SIGBREAK;
#else
int const sigClosed = SIGHUP;
#endif
volatile sig_atomic_t windowClosed = 0;
void signalHandler( int )
{
windowClosed = 1;
}
// ...
signal( sigClosed, signalHandler );
while ( windowClosed == 0 ) {
// ...
}
If you're doing any input from the console in the loop, you'll have the
be prepared for the input to fail (which you should be anyway).

Related

Is it possible a kill a command launched using system api in C? If not any alternatives?

I am launching a command using system api (I am ok with using this api with C/C++). The command I pass may hang at times and hence I would like to kill after certain timeout.
Currently I am using it as:
system("COMMAND");
I want to use it something like this:
Run a command using a system independent API (I don't want to use CreateProcess since it is for Windows only) Kill the process if it does not exit after 'X' Minutes.
Since system() is a platform-specific call, there cannot be a platform-independent way of solving your problem. However, system() is a POSIX call, so if it is supported on any given platform, the rest of the POSIX API should be as well. So, one way to solve your problem is to use fork() and kill().
There is a complication in that system() invokes a shell, which will probably spawn other processes, and I presume you want to kill all of them, so one way to do that is to use a process group. The basic idea is use fork() to create another process, place it in its own process group, and kill that group if it doesn't exit after a certain time.
A simple example - the program forks; the child process sets its own process group to be the same as its process ID, and uses system() to spawn an endless loop. The parent process waits 10 seconds then kills the process group, using the negative value of the child process PID. This will kill the forked process and any children of that process (unless they have changed their process group.)
Since the parent process is in a different group, the kill() has no effect on it.
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
int main() {
pid_t pid;
pid = fork();
if(pid == 0) { // child process
setpgid(getpid(), getpid());
system("while true ; do echo xx ; sleep 5; done");
} else { // parent process
sleep(10);
printf("Sleep returned\n");
kill(-pid, SIGKILL);
printf("killed process group %d\n", pid);
}
exit(0);
}
There is no standard, cross-platform system API. The hint is that they are system APIs! We're actually "lucky" that we get system, but we don't get anything other than that.
You could try to find some third-party abstraction.
Check below C++ thread based attempt for linux. (not tested)
#include <iostream>
#include <string>
#include <thread>
#include <stdio.h>
using namespace std;
// execute system command and get output
// http://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-output-of-command-within-c
std::string exec(const char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
void system_task(string& cmd){
exec(cmd.c_str());
}
int main(){
// system commad that takes time
string command = "find /";
// run the command in a separate thread
std::thread t1(system_task, std::ref(command));
// gives some time for the system task
std::this_thread::sleep_for(chrono::milliseconds(200));
// get the process id of the system task
string query_command = "pgrep -u $LOGNAME " + command;
string process_id = exec(query_command.c_str());
// kill system task
cout << "killing process " << process_id << "..." << endl;
string kill_command = "kill " + process_id;
exec(kill_command.c_str());
if (t1.joinable())
t1.join();
cout << "continue work on main thread" << endl;
return 0;
}
I had a similar problem, in a Qt/QML development: I want to start a bash command, while continuing to process events on the Qt Loop, and killing the bash command if it takes too long.
I came up with the following class that I'm sharing here (see below), in hope it may be of some use to people with a similar problem.
Instead of calling a 'kill' command, I call a cleanupCommand supplied by the developper. Example: if I'm to call myscript.sh and want to check that it won't last run for more than 10 seconds, I'll call it the following way:
SystemWithTimeout systemWithTimeout("myScript.sh", 10, "killall myScript.sh");
systemWithTimeout.start();
Code:
class SystemWithTimeout {
private:
bool m_childFinished = false ;
QString m_childCommand ;
int m_seconds ;
QString m_cleanupCmd ;
int m_period;
void startChild(void) {
int rc = system(m_childCommand.toUtf8().data());
if (rc != 0) SYSLOG(LOG_NOTICE, "Error SystemWithTimeout startChild: system returned %d", rc);
m_childFinished = true ;
}
public:
SystemWithTimeout(QString cmd, int seconds, QString cleanupCmd)
: m_childFinished {false}, m_childCommand {cmd}, m_seconds {seconds}, m_cleanupCmd {cleanupCmd}
{ m_period = 200; }
void setPeriod(int period) {m_period = period;}
void start(void) ;
};
void SystemWithTimeout::start(void)
{
m_childFinished = false ; // re-arm the boolean for 2nd and later calls to 'start'
qDebug()<<"systemWithTimeout"<<m_childCommand<<m_seconds;
QTime dieTime= QTime::currentTime().addSecs(m_seconds);
std::thread child(&SystemWithTimeout::startChild, this);
child.detach();
while (!m_childFinished && QTime::currentTime() < dieTime)
{
QTime then = QTime::currentTime();
QCoreApplication::processEvents(QEventLoop::AllEvents, m_period); // Process events during up to m_period ms (default: 200ms)
QTime now = QTime::currentTime();
int waitTime = m_period-(then.msecsTo(now)) ;
QThread::msleep(waitTime); // wait for the remaning of the 200 ms before looping again.
}
if (!m_childFinished)
{
SYSLOG(LOG_NOTICE, "Killing command <%s> after timeout reached (%d seconds)", m_childCommand.toUtf8().data(), m_seconds);
int rc = system(m_cleanupCmd.toUtf8().data());
if (rc != 0) SYSLOG(LOG_NOTICE, "Error SystemWithTimeout 164: system returned %d", rc);
m_childFinished = true ;
}
}
I do not know any portable way to do that in C nor C++ languages. As you ask for alternatives, I know it is possible in other languages. For example in Python, it is possible using the subprocess module.
import subprocess
cmd = subprocess.Popen("COMMAND", shell = True)
You can then test if COMMAND has ended with
if cmd.poll() is not None:
# cmd has finished
and you can kill it with :
cmd.terminate()
Even if you prefere to use C language, you should read the documentation for subprocess module because it explains that internally it uses CreateProcess on Windows and os.execvp on Posix systems to start the command, and it uses TerminateProcess on Windows and SIG_TERM on Posix to stop it.

Waiting for interrupt-loop

I need a code construction for my project which waits for some time, but when there is an interrupt (e.g. incoming udp packets) it leaves this loop, does something, and after this restart the waiting.
How can I implement this? My first idea is using while(wait(2000)), but wait is a void construct...
Thank you!
I would put the loop inside a function
void awesomeFunction() {
bool loop = true;
while (loop) {
wait(2000);
...
...
if (conditionMet)
loop = false;
}
}
Then i would put this function inside another loop
while (programRunning) {
awesomeFunction();
/* Loop ended, do stuff... */
}
There are a few things I am not clear about from the question. Is this a multi-threaded application, where one thread handles (say) the UDP packets, and the other waits for the event, or is this single-threaded? You also didn't mention what operating system this is, which is relevant. So I am going to assume Linux, or something that supports the poll API, or something similar (like select).
Let's assume a single threaded application that waits for UDP packets. The main idea is that once you have the socket's file descriptor, you have an infinite loop on a call to poll. For instance:
#include <poll.h>
// ...
void handle_packets() {
// m_fd was created with `socket` and `bind` or `connect`.
struct pollfd pfd = {.fd = m_fd, .events = POLLIN};
int timeout;
timeout = -1; // Wait indefinitely
// timeout = 2000; // Wait for 2 seconds
while (true) {
pfd.revents = 0;
poll(&pfd, 1, timeout);
if ((pfd.revents & POLLIN) != 0) {
handle_single_packet(); // Method to actually read and handle the packet
}
if ((pfd.revents & (POLLERR | POLLHUP)) != 0) {
break; // return on error or hangup
}
}
}
A simple example of select can be found here.
If you are looking at a multi-threaded application, trying to communicate between the two threads, then there are several options. Two of which are:
Use the same mechanism above. The file descriptor is the result of a call to pipe. The thread sleeping gets the read end of the pipe. The thread waking get the write end, and writes a character when it's time to wake up.
Use C++'s std::condition_variable. It is documented here, with a complete example. This solution depends on your context, e.g., whether you have a variable that you can wait on, or what has to be done.
Other interrupts can also be caught in this way. Signals, for instance, have a signalfd. Timer events have timerfd. This depends a lot on what you need, and in what environment you are running. For instance, timerfd is Linux-specific.

C++ Interrupts?

I was wondering if C++ had any way of doing interrupts. I want one program to store information in a text file, while the other one prints a statement depending on what is in the text file. Since I want it to be as accurate as possible, I need the print program to be interrupted when the update program updates the file.
C++ itself doesn't give this capability, it knows nothing of other programs that may or may not be running.
What you need to look into is IPC (inter-process communications), something your operating system will probably provide.
Things like signals, shared memory, semaphores, message queues and so on.
Since you seem to be using the file itself as the method of delivering content to the other process, signals are probably the way to go. You would simply raise a signal from process A to process B and a signal handler would run in the latter.
Of course this all depends on which operating system you're targeting.
If you are using Windows you can use FindFirstChangeNotification.
Here's some old code I have. This is run in it's own thread:
DWORD CDiskWatcher::Run(void *vpParameter)
{
CFileNotifyInterface *pIface = (CFileNotifyInterface *)vpParameter;
HANDLE handles[2];
handles[0] = m_hQuitEvent;
handles[1] = ::FindFirstChangeNotification(m_szPath, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE|FILE_NOTIFY_CHANGE_FILE_NAME);
DWORD dwObject;
if (INVALID_HANDLE_VALUE != handles[1]) {
do {
// Wait for the notification
dwObject = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (WAIT_OBJECT_0 + 1 == dwObject) {
// Continue waiting...
::FindNextChangeNotification(handles[1]);
pIface->FireFileSystemChange(m_szPath);
}
} while (WAIT_OBJECT_0 != dwObject);
// Close handle
::FindCloseChangeNotification(handles[1]);
}
return 0;
}
Note m_hQuitEvent is created with CreateEvent() and CFileNotifyInterface is for callbacks:
class CFileNotifyInterface
{
public:
virtual void FireFileSystemChange(const char *szPath) = 0;
};

gSoap: how to gracefully shutdown the webservice application?

I'm using gSoap to write a webservice. It's running as a console application. In all gSoap examples I see, that requests are dispatched in infinite loop like for(;;;) even in multi-threaded version.
But how can I make my webservice to terminate gracefully when, say, user presses space on the console?
Preferably:
stop accepting new connections;
Serve existing ones;
Exit from application
The only solution I came up so far is using timeouts
soap->recv_timeout = 20;
soap->send_timeout = 20;
soap->connect_timeout = 5;
soap->accept_timeout = 5;
Then all blocking functions return periodically. But this is not ideal for me, because I want to be able to terminate the app quickly even if there is an ongoing transmission, but at the same time, don't want to compromise reliability on a slow/flaky connection (it's an embedded device connected via GPRS).
The section 7.2.4 How to Create a Multi-Threaded Stand-Alone Service in the documentation has example code for writing an accept loop. You need to write your own accept loop and add signal handling so it responds to Ctrl-C.
stop accepting new connections:
Leave the loop so you stop calling accept.
Serve existing ones:
The threads need to inform you when they are finished, so you can exit when the number of active clients is zero. (boost::thead_group has a join_all which does exactly that.)
Exit from application:
What you need to do is register signal handler so when you terminate your application using Ctrl + C, it calls you registered function where you can gracefully terminates.
e.g
class gsoap_test {
public:
void start() {
running_ = true;
while(running_) {
//gsoap threads
}
//stop and cleanup
}
void stop() {
running_ = false;
}
private:
bool running_;
};
//global variable
gsoap_test gsoap;
void sighandler(int sig)
{
std::cout<< "Signal caught..." << std::endl;
//Stop gracefully here
gsoap.stop();
exit(0);
}
int main(int argc, char** argv) {
//register signal
signal(SIGABRT, &sighandler);
signal(SIGTERM, &sighandler);
signal(SIGINT, &sighandler);
gsoap.start();
return EXIT_SUCCESS;
}

How to handle a ctrl-break signal in a command line interface

Before I begin, I want to clarify that this is not a command-line tool, but an application that accepts commands through it's own command-line interface.
Edit: I must apologize about my explanation from before, apparently I didn't do a very good job at explaining it. One more time...
I am building a command-line interface application that accepts commands from a user. I have a signal handler setup to catch the signals, which then sets a flag that I need to terminate the application. The problem I'm having is all of the console functions I can find are blocking, which means that I can't detect that I need to exit from my console processing loop until the user presses a key (or enter, depending on the function).
Is there some standard way I can do either non-block console interaction, or is there an elegant way to structure the program so that if I just terminate from the signal thread, that everything will be handled and released properly (please don't mis-understand this, I know how this could be done using locking and releasing the resources from the signaling thread, but this could get messy, so I'd rather avoid it)
Hopefully that explanation makes more sense...
OK - this is working for me on Windows & is portable - notice the #ifdef SIGBREAK - this isn't a standard signal.
#include <csignal>
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
namespace
{
volatile sig_atomic_t quit;
void signal_handler(int sig)
{
signal(sig, signal_handler);
quit = 1;
}
}
int main()
{
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
#ifdef SIGBREAK
signal(SIGBREAK, signal_handler);
#endif
/* etc */
while (!quit)
{
string s;
cin >> s;
cout << s << endl;
}
cout << "quit = " << quit << endl;
}
On *nix, you can use the signal function to register a signal handler:
#include <signal.h>
void signal_handler(int sig)
{
// Handle the signal
}
int main(void)
{
// Register the signal handler for the SIGINT signal (Ctrl+C)
signal(SIGINT, signal_handler);
...
}
Now, whenever someone hits Ctrl+C, your signal handler will be called.
In Windows: SetConsoleCtrlHandler
On a *nix based system you might not really need a signal handler for this to work. You could specify that you want to ignore the SIGINT call
int main(void)
{
// Register to ignore the SIGINT signal (Ctrl+C)
signal(SIGINT, SIG_IGN);
while(1)
{
retval = my_blocking_io_func();
if(retval == -1 && errno == EINTR)
{
// do whatever you want to do in case of interrupt
}
}
}
The important way that this works is to recognize that non-blocking functions do get interrupted. Normally, you would realize that the blocking function failed (e.g. read()) and reattempt the function. If it was some other value you would take the appropriate error related action.
A better *nix solution that is thread safe is to use pthread_sigmask() instead of signal().
For example, this is how you signore SIGINT, SIGTERM, and SIGPIPE in the current thread and future spawned threads:
sigset_t waitset;
sigemptyset(&waitset);
sigaddset(&waitset, SIGINT);
sigaddset(&waitset, SIGTERM);
sigaddset(&waitset, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &waitset, NULL);

Categories