Wednesday, October 13, 2010

Ctrl-c signal catching from C program and from MATLAB's mex

In C the signal handling can be done by replacing the signal handle. The function signal(SIGINT,func) places the handler for  SIGINT with your definition of void func(int sig);

#include <signal.h>;
#include <stdio.h>;

/* * Ctrl-C signal catching infrastructure * */
/* This global variable is accessible from all the files using extern*/

short INTERRUPTED;  

/* This function that handles the signal just changes the state of 
   INTERRUPTED. This variable is checked periodically in the main loop*/
void sigproc_ctrlC(int sig)
{
   /* To access the global variable must be defined as extern */
   extern short INTERRUPTED;       
   INTERRUPTED =1;
   printf("Ctrl-C pressed\n");
}

int main() {
   /* * INTERRUPT SIGNAL HANDLING * */
   /* The global variable must be defined as extern */
   extern short INTERRUPTED;   

   /* Initial value for INTERRUPTED*/
   INTERRUPTED=0;

   /* Associate the signal handler to the SIGINT */
   signal(SIGINT, sigproc_ctrlC);  


   printf("Press Ctrl-C to interrupt\n");
   /* Infinite loop*/
   while ( !INTERRUPTED ) {  
      printf("INTERRUPTED=%d\n",INTERRUPTED);

   }
}



We cannot apply this to MEX files, because in the MATLAB's enviroment there is already a signal handler in place, and if we replace it for our own, then our handler stays there for the remaining of the MATLAB's execution.
We need to reset the original handler after finishing the execution of our code. 
The following program will do the trick, and also applies to the standard C programs. The sigaction(SIGINT, &act, &oact) function allow to replace the SIGING handler with (act) but also returns a pointer to the original one (oact).


#include <signal.h>;
#include <stdio.h>;
#include <mex.h>;

/* * Ctrl-C signal catching infrastructure * */
/* This global variable is accessible from all the files using extern*/
short INTERRUPTED;  

/* This function that handles the signal just changes the state of 
   INTERRUPTED. This variable is checked periodically in the main loop*/
void sigproc_ctrlC(int sig)
{
   /* To access the global variable must be defined as extern */
   extern short INTERRUPTED;       
   INTERRUPTED =1;
   printf("Ctrl-C pressed\n");
}

/* Global variables for storing the signal handlers */
struct sigaction act, oact;


void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]){
   /* * INTERRUPT SIGNAL HANDLING * */
   /* The global variable must be defined as extern */
   extern short INTERRUPTED;   

   /* Initial value for INTERRUPTED*/
   INTERRUPTED=0;

   /* Save and over-ride old SIGINT behaviour */
   act.sa_handler = sigproc_ctrlC;
   sigaction(SIGINT, &act, &oact);



   /* Infinite loop */
   while ( !INTERRUPTED ) {
      printf("INTERRUPTED=%d\n",INTERRUPTED);
   }

   /* Reset the original handler */
   printf("Resetting signal handler for SIGINT\n");
   sigaction(SIGINT, &oact, &act);
}



Sources:
http://www.mathworks.cn/matlabcentral/newsreader/view_thread/23450
http://newsgroups.derkeiler.com/Archive/Comp/comp.soft-sys.matlab/2006-06/msg01751.html

No comments:

Post a Comment