From: Jean-Marc Pigeon (Delson) Date: Wed, 10 Jul 2024 13:20:37 +0000 (-0400) Subject: signal handling implementation X-Git-Tag: tag-0.2~2 X-Git-Url: https://jmp-git.ovh.safe.ca/?a=commitdiff_plain;h=dc495403d3f63fb95c076d726a3af5ebeb2223fc;p=jmp%2Fmailleur signal handling implementation --- diff --git a/app/maild.c b/app/maild.c index 6067d1a..b177d8f 100644 --- a/app/maild.c +++ b/app/maild.c @@ -12,6 +12,7 @@ #include "subrou.h" #include "unipar.h" #include "uniprc.h" +#include "unisig.h" #include "modrec.h" //port listening format is "IP:PORT NUMBER:num iteration" @@ -38,7 +39,6 @@ while (proceed==true) { switch (phase) { case 0 : //looping forever email receiving processes for (int i=0;i0) { + (void) prc_nozombie(); (void) sleep(2); phase--; //let send signal again } @@ -128,14 +130,18 @@ while (proceed==true) { (void) rou_modesubrou(true); (void) par_modeunipar(true); (void) prc_modeuniprc(true); + (void) sig_modeunisig(true); (void) rec_modemodrec(true); + (void) sig_trapsignal(true,sig_alrm); break; case 3 : //doing main tash (void) task(5); break; case 4 : //doing main tash (void) prc_cleantitle(); + (void) sig_trapsignal(false,sig_alrm); (void) rec_modemodrec(false); + (void) sig_modeunisig(false); (void) prc_modeuniprc(false); (void) par_modeunipar(false); (void) rou_modesubrou(false); diff --git a/lib/Makefile b/lib/Makefile index b31bbf9..99c8e8c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,7 +17,7 @@ clean : #-------------------------------------------------------------------- OBJS= \ modrec.o \ - unipar.o uniprc.o \ + unipar.o uniprc.o unisig.o \ subrou.o objs : $(OBJS) @@ -29,13 +29,17 @@ modrec.o: \ subrou.h \ modrec.h modrec.c +unipar.o: \ + subrou.h \ + unipar.h unipar.c + uniprc.o: \ subrou.h \ uniprc.h uniprc.c -unipar.o: \ +unisig.o: \ subrou.h \ - unipar.h unipar.c + unisig.h unisig.c subrou.o: \ subrou.h subrou.c diff --git a/lib/modrec.c b/lib/modrec.c index bd06d68..b97d5c7 100644 --- a/lib/modrec.c +++ b/lib/modrec.c @@ -5,11 +5,11 @@ /* */ /********************************************************/ #include -#include #include #include "subrou.h" #include "uniprc.h" +#include "unisig.h" #include "modrec.h" static _Bool modopen; //boolean module open/close @@ -22,17 +22,19 @@ static _Bool modopen; //boolean module open/close /* */ /********************************************************/ //procedure to receive email form outside -void rec_getemail() +void rec_getemail(int attend) { -int attend; - -attend=(random()%7)+2; (void) rou_alert(0,"JMPDBG getemail with pid='%06d' (wait for '%0d')", getpid(),attend); (void) prc_settitle("JMPDBG getemail with pid='%06d' (wait for '%0d')", getpid(),attend); -(void) sleep(attend); +while (attend>0) { + (void) sleep(1); + if (hangup==true) + break; + attend--; + } (void) rou_alert(0,"JMPDBG exiting from pid='%06d'",getpid()); } /* @@ -58,8 +60,10 @@ if (mode!=modopen) { case true : (void) rou_modesubrou(mode); (void) prc_modeuniprc(mode); + (void) sig_modeunisig(mode); break; case false : + (void) sig_modeunisig(mode); (void) prc_modeuniprc(mode); (void) rou_modesubrou(mode); break; diff --git a/lib/modrec.h b/lib/modrec.h index f806343..0b0a29d 100644 --- a/lib/modrec.h +++ b/lib/modrec.h @@ -10,7 +10,7 @@ #include //procedure to receive email form outside -extern void rec_getemail(); +extern void rec_getemail(int attend); //homework to be done before starting/stoping module. extern int rec_modemodrec(_Bool mode); diff --git a/lib/subrou.c b/lib/subrou.c index c47a0ef..84f78d9 100644 --- a/lib/subrou.c +++ b/lib/subrou.c @@ -4,18 +4,21 @@ /* Module for low level subroutine */ /* */ /********************************************************/ +#include #include +#include #include #include #include #include +#include #include "subrou.h" //version definition #define VERSION "0.1" -#define RELEASE "11" +#define RELEASE "12" //Public variables PUBLIC int debug=0; //debug level @@ -31,6 +34,26 @@ static _Bool modopen; //boolean module open/close static time_t off64_time=(time_t)0; static time_t off_date=(time_t)0; /* + +*/ +/********************************************************/ +/* */ +/* Procedure to find out a possible drop zone */ +/* for abort() core memory dump. */ +/* */ +/********************************************************/ +static char *get_dropzone() + +{ +const char *dropzone="/tmp/"APPNAME"-crash"; + +char command[100]; + +(void) snprintf(command,sizeof(command)-2,"mkdir -p %s",dropzone); +(void) system(command); +return strdup(dropzone); +} +/* ^L */ /********************************************************/ @@ -159,6 +182,113 @@ if (modopen==false) { return status; } /* + +*/ +/********************************************************/ +/* */ +/* Subroutine to CORE-DUMP the application */ +/* */ +/********************************************************/ +void rou_crash(const char *fmt,...) + +{ +#define RELAX 5 +va_list args; +char strloc[10000]; + +va_start(args,fmt); +(void) vsnprintf(strloc,sizeof(strloc),fmt,args); +(void) rou_alert(0,"Crashed on purpose:"); +(void) rou_alert(0,"\t--> '%s'",strloc); +(void) rou_alert(0,"Crash delayed by '%d' second",RELAX); +(void) sleep(RELAX); //To avoid immediat restart +va_end(args); +(void) kill(getpid(),SIGSEGV); +(void) exit(-1); //unlikely to reach here +} +/* + +*/ +/********************************************************/ +/* */ +/* Procedure to display an core_dump */ +/* message and terminate application */ +/* */ +/********************************************************/ +void rou_core_dump(const char *fmt,...) + +{ +#define MAXCRASH 10 //maximun crash file within drop zone +#define COREDELAY 5 //number of second for core delay + +va_list args; +char *crashdir; +_Bool doabort; +_Bool proceed; +int phase; + +va_start(args,fmt); +crashdir=(char *)0; +doabort=false; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //find out if crashdir is existing + if ((crashdir=get_dropzone())==(char *)0) + phase=999; //no need to go further. + break; + case 1 : //can we access the crash dir + if (chdir(crashdir)<0) { //Unable to access crashdir + (void) free(crashdir); + phase=999; //no need to go further. + } + break; + case 2 : //no too much crash so fare? + DIR *dirp; + + (void) rou_alert(0,"Trying to store core-dump within directory <%s>", + crashdir); + if ((dirp=opendir(crashdir))!=(DIR *)0) { + int nument; + struct dirent *entry; + + nument=0; + while ((entry=readdir(dirp))!=(struct dirent *)0) { + if (entry->d_type==DT_REG) + nument++; + } + (void) closedir(dirp); + if (nument>MAXCRASH) { + (void) rou_alert(0,"Aborting Coredump file generation!"); + (void) rou_alert(0,"Too many crash files already within <%s>", + crashdir); + phase=999; //No allowed to do abort + } + } + (void) free(crashdir); + break; + case 3 : //Ok we can call abort + doabort=true; + break; + default : + proceed=false; + break; + } + phase++; + } +(void) sleep(COREDELAY); /*to avoid crash avalanche */ +(void) rou_valert(LOG_INFO,fmt,args); +va_end(args); +if (doabort==true) + (void) abort(); /*doing to do the abort */ +(void) rou_alert(0,"Unable to dump core memory"); +(void) exit(-1); //Theoriticaly unreachabe if + //abort was allowed +#undef MAXCRASH +#undef COREDELAY +} +/* ^L */ /********************************************************/ @@ -179,10 +309,9 @@ status=0; if (mode!=modopen) { switch ((int)mode) { case true : - debug=0; - off64_time=(time_t)0; - off_date=(time_t)0; - (void) srand((int)(M_PI*100000000)); + (void) srand(getpid()*355); + if (foreground==true) + (void) srand((int)(M_PI*100000000)); if (appname!=(char *)0) (void) free(appname); appname=strdup(APPNAME); diff --git a/lib/subrou.h b/lib/subrou.h index 021f142..ec36f11 100644 --- a/lib/subrou.h +++ b/lib/subrou.h @@ -33,10 +33,19 @@ extern char *rou_apppath(const char *path); //via syslog (LOG_INFO) using variable argument list macros void rou_valert(const int dlevel,const char *fmt,va_list ap); +//return a difference between 2 chrono //to display message on console (verbose mode) or //via syslog (LOG_DAEMON) extern void rou_alert(const int dlevel,const char *fmt,...); +//To do an on purpose crash the application with an +//explication message +extern void rou_crash(const char *fmt,...); + +//To do an on purpose application memory core dump +//with an explication message +extern void rou_core_dump(const char *fmt,...); + //homework to be done before starting/stoping module. extern int rou_modesubrou(_Bool mode); diff --git a/lib/uniprc.c b/lib/uniprc.c index d56d47b..8b00246 100644 --- a/lib/uniprc.c +++ b/lib/uniprc.c @@ -384,7 +384,7 @@ va_end(args); int prc_modeuniprc(_Bool mode) { -#define OPEP "unipar.c:uni_modeuniprc" +#define OPEP "unipar.c:prc_modeuniprc" int status; diff --git a/lib/uniprc.h b/lib/uniprc.h index e197a60..66a3207 100644 --- a/lib/uniprc.h +++ b/lib/uniprc.h @@ -48,7 +48,7 @@ extern _Bool prc_locking(const char *lockname,int lock,int tentative); //procedure to put application in deamon mode extern pid_t prc_divedivedive(); -//homework to be done before starting/stoping module. +//homework to be done before starting/stopping module. extern int prc_modeuniprc(_Bool mode); #endif diff --git a/lib/unisig.c b/lib/unisig.c new file mode 100644 index 0000000..01c96c6 --- /dev/null +++ b/lib/unisig.c @@ -0,0 +1,236 @@ +// vim: smarttab tabstop=8 shiftwidth=2 expandtab +/********************************************************/ +/* */ +/* Module for signal handling level */ +/* */ +/********************************************************/ +#include +#include +#include +#include + +#include "unisig.h" + +PUBLIC _Bool hangup; //Hangup signal received +PUBLIC _Bool reload; //reload configuration signal received +PUBLIC _Bool wakeup; //application wakeup under an alarm + +static _Bool modopen; //boolean module open/close +/* + +*/ +/********************************************************/ +/* */ +/* Procedure to catch signal and do what is */ +/* needed. */ +/* */ +/********************************************************/ +static void gotsigsegv(int sig) + +{ +#define OPEP "unisig.c:trapsigsegv," + +switch (sig) { + case SIGSEGV : + (void) rou_core_dump("Genuine memory violation (Bug?)"); + break; + default : + (void) rou_core_dump("%s Unexpected signal <%s> received (BUG!)", + OPEP,strsignal(sig)); + break; + } +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to set a signal handler in case of */ +/* segmentation violation. */ +/* */ +/********************************************************/ +static void trapsigsegv(_Bool onoff,sighandler_t trap) + +{ +static _Bool prvon=false; +static struct sigaction oldsa; + +if (onoff==true) { + struct sigaction newsa; + + if (prvon==true) //in case we set signal twice + (void) sigaction(SIGSEGV,&oldsa,(struct sigaction *)0); + newsa.sa_flags=0; + newsa.sa_handler=trap; + (void) sigemptyset(&newsa.sa_mask); + (void) sigaction(SIGSEGV,&newsa,&oldsa); + } +else { + (void) sigaction(SIGSEGV,&oldsa,(struct sigaction *)0); + } +prvon=onoff; +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to trap "critical" signal and set */ +/* flag accordingly; */ +/* */ +/********************************************************/ +void sig_alrm(int sig) + +{ +#define OPEP "unisig.c:sig_alrm" + +(void) rou_alert(9,"%s, signal <%s> received",OPEP,strsignal(sig)); +switch (sig) + { + case SIGCHLD : + while (waitpid(-1,(int *)0,WNOHANG)>0); + break; + case SIGQUIT : + case SIGTERM : + hangup=true; + break; + case SIGINT : + case SIGHUP : + reload=true; + break; + case SIGALRM : //got an alarm, just to wakeup + wakeup=true; + break; + case SIGUSR1 : + debug++; + if (debug>10) + debug=10; + (void) rou_alert(0,"%s deamon, new increased debug level now set to '%d'", + APPNAME,debug); + break; + case SIGUSR2 : + debug--; + if (debug<0) + debug=0; + (void) rou_alert(0,"%s deamon, new decreased debug level now set to '%d'", + APPNAME,debug); + break; + default : + (void) rou_alert(0,"Unexpected Signal [%d]/<%s> received", + sig,strsignal(sig)); + break; + } +//able to receive next signal +(void) signal(sig,sig_alrm); +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to trap all meaningfull signal needed */ +/* bay application */ +/* */ +/********************************************************/ +void sig_trapsignal(_Bool onoff,sighandler_t trap) + +{ +#define OPEP "modbck.c:settrap" +#define NUMINTR 7 + +static struct sigaction *olds[NUMINTR]; +static _Bool alldone=false; + +if (onoff==alldone) { + switch ((int)onoff) { + case true : + (void) rou_crash("%s signal trap already set (Bug?)",OPEP); + break; + case false : + (void) rou_crash("%s signal trap already UNset (Bug?)",OPEP); + break; + default : + (void) rou_crash("%s unproper settrap value (very bad Bug!)",OPEP); + break; + } + } +if (onoff==true) { + struct sigaction *newsa; + int i; + + newsa=(struct sigaction *)calloc(1,sizeof(struct sigaction)); + newsa->sa_flags=0; + newsa->sa_handler=trap; + for (i=0;i +#include + +#include "subrou.h" + +typedef void (*sighandler_t)(int); + + +extern _Bool hangup; //Hangup signal received +extern _Bool reload; //reload configuration signal received +extern _Bool wakeup; //just got a signal + +//"standard" signal trap +extern void sig_alrm(int sig); + +//trapping application signal (SIGTERM, SIGHUP, etc... +extern void sig_trapsignal(_Bool onoff,sighandler_t trap); + +//homework to be done before starting/stopping module. +extern int sig_modeunisig(_Bool mode); + +#endif