The Allegro Wiki is migrating to github at https://github.com/liballeg/allegro_wiki/wiki

Signals on Allegro

From Allegro Wiki
Jump to: navigation, search

Why you came here

Sometimes is the desire of a programmer to catch the crtl - c user action. Why ? Cause sometimes there's the need to terminate, classes, structs, objects, connections, maybe close a file (with a final message saying "program aborted by user" in the case of logs.. etc.).

Allegro for example, deallocates all the system resources previously invoked or loaded along the program. In the allegro_init function and allegro itself use something called signals and this are defined in the c library of almost any popular compiler today. Im focusing in gcc particulary.

Signals

Signals are software interrupt triggers. The process are notified by the system about the signal. For almost all signals the processes then have the following 3 options:

  1. To IGNORE the signal: The process ignores the signal and continue execution normally.
  2. To allow DEFAULT systema behavior: The process interrupts and the system will handle the signal.
  3. To HANDLE the signal: The process will take control of the situation by means of a callback function called signal handler. There the process will evaluate what to do, e.g.: to terminate the process, to correct some situation, to notify the user about something that is happening at the moment.

What we are going to explain in this wiki is how to handle a ctrl - c user action in an allegro program.

But first we need to understand a couple of things. First, the signal we are trying to handle is called SIGINT (it represents the numerical value of the signal raised whenever the user hits ctrl-c). Second, we install a signal handler with the function signal. Third, we have to respect the fact that allegro actually has a plan about the SIGINT signal (in programming terms it means that allegro has previously installed a handler to manage this signal raising).

Handling user ctrl-c in allegro

The first you should do is to understand what was the allegro plan for the ctrl-c user action, and install your handler:

#include <signal.h>

struct sigaction allegro_handler; 
void myHandler(int);

void installFoo (void){
 /* Assuming allegro_init was previously invoked */
 sigaction(SIGINT,0x0,&allegro_handler); // Here we save in the allegro_handler struct, the allegro preinstalled SIGINT handler.
 signal(SIGINT,myHandler);
}

Now we write our handling function:

void myHandler(int signum){

 doMyDeallocationStuff();
 shutDownTheWhatEverLib();
 deallocateAllTheGigasIGotInRam();
 disconnectTheProcessFromTheNetworkCleanly();
 
 /* And now, pass the ball to allegro, cause it wants to do stuff also, you know */
 allegro_handler.sa_handler(signum);

}

One last thing: you may be thinking what is that param signum all about? Well, it turns that a single handler can manage a variety of signals thats why theres a signum param: to indicate what kind of signal is the one the handler is to be aware of. But for our case its going to be only and exclusevly SIGINT, cause we associated this signal just to myHandler function.

Conclusions

  1. Its easy to manage the ctrl-c user action. glibc provides a lot of mechanisms to do this in an easy way.
  2. A better way to make games or programs is to try to understand the underlying levels of your code (the apis like allegro, the operating system in general and its interfaces like glibc, etc.)