]> SAFE projects GIT repository - jmp/mailleur/commitdiff
signal handling implementation
authorJean-Marc Pigeon (Delson) <jmp@safe.ca>
Wed, 10 Jul 2024 13:20:37 +0000 (09:20 -0400)
committerJean-Marc Pigeon (Delson) <jmp@safe.ca>
Wed, 10 Jul 2024 13:20:37 +0000 (09:20 -0400)
app/maild.c
lib/Makefile
lib/modrec.c
lib/modrec.h
lib/subrou.c
lib/subrou.h
lib/uniprc.c
lib/uniprc.h
lib/unisig.c [new file with mode: 0644]
lib/unisig.h [new file with mode: 0644]

index 6067d1aec46d9b80d92f2ee8963fbb4c0e645971..b177d8f51eb527292f087fda1640661aedb17e62 100644 (file)
@@ -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;i<iteration;i++) {
-        (void) random();
         if (pidlst[i]!=(pid_t)0) {
           if (prc_checkprocess(pidlst[i])==true) 
             continue;
@@ -48,15 +48,16 @@ while (proceed==true) {
             pidlst[i]=(pid_t)0;
             break;
           case  0       :
-            (void) rec_getemail();
+            (void) rec_getemail((random()%10)+10);
             (void) exit(0);     //email receiving task terminated
             break;
           default       :       
             break;
           }
         }
-      phase--;                  //let try again
       (void) sleep(2);          //next check in 5 second
+      if (hangup==false)        //lets try again
+        phase--;                //same phase
       (void) prc_nozombie();
       break;
     case 1      :       //Terminating all remaining process
@@ -75,6 +76,7 @@ while (proceed==true) {
             pidlst[i]=(pid_t)0;
           }
         if (stillrun>0) {
+          (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);
index b31bbf9dd9b48c9b6d42c778ef9d827b33fac74e..99c8e8c821819bf02ec0fbc693c3ecc2284484c5 100644 (file)
@@ -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
index bd06d6823d0a7a170e33049d5bbd31c32ce1dda3..b97d5c76faf87dc5bea8201408aaf02d75ec46f3 100644 (file)
@@ -5,11 +5,11 @@
 /*                                                     */
 /********************************************************/
 #include        <stdio.h>
-#include        <stdlib.h>
 #include        <unistd.h>
 
 #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;
index f80634397661cc1924f4fdc7630305a9b798010a..0b0a29d4f7e480814ea9563f60145eb29a91c50c 100644 (file)
@@ -10,7 +10,7 @@
 #include        <stdbool.h>
 
 //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);
index c47a0efa528ea6745d507201b4eba39d3fb10acf..84f78d9e2b6532cc60f65b204917207945a9ea47 100644 (file)
@@ -4,18 +4,21 @@
 /*     Module for low level subroutine                 */
 /*                                                     */
 /********************************************************/
+#include        <dirent.h>
 #include        <math.h>
+#include        <signal.h>
 #include        <stdio.h>
 #include        <stdlib.h>
 #include        <string.h>
 #include        <syslog.h>
+#include        <unistd.h>
 
 #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;
 /*
+\f
+*/
+/********************************************************/
+/*                                                     */
+/*     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;
 }
 /*
+\f
+*/
+/********************************************************/
+/*                                                     */
+/*     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
+}
+/*
+\f
+*/
+/********************************************************/
+/*                                                     */
+/*     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);
index 021f142a61b8b0b4b8e86f0eb4a9f76cd2a2c331..ec36f11c611858875c6c0c1e06939d72ef8b99b7 100644 (file)
@@ -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);
 
index d56d47b098388e3ccf890a3c3f4ea90b85743a12..8b00246b48a9d3d22847853a904246e7f75854d5 100644 (file)
@@ -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;
 
index e197a602cde26ad0ca98a3771cac5cf01d914d34..66a3207fd6d33d908c74022cb8566ec1b60dd15f 100644 (file)
@@ -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 (file)
index 0000000..01c96c6
--- /dev/null
@@ -0,0 +1,236 @@
+// vim: smarttab tabstop=8 shiftwidth=2 expandtab
+/********************************************************/
+/*                                                     */
+/*     Module for signal handling level                */
+/*                                                     */
+/********************************************************/
+#include        <sys/wait.h>
+#include        <stdlib.h>
+#include        <stdio.h>
+#include        <string.h>
+
+#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
+/*
+\f
+*/
+/********************************************************/
+/*                                                     */
+/*     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<NUMINTR;i++) {
+    if (olds[i]==(struct sigaction *)0) 
+      olds[i]=calloc(1,sizeof(struct sigaction));
+    }
+  (void) sigaction(SIGUSR2,newsa,olds[0]);
+  (void) sigaction(SIGUSR1,newsa,olds[1]);
+  (void) sigaction(SIGINT,newsa,olds[2]);
+  (void) sigaction(SIGTERM,newsa,olds[3]);
+  (void) sigaction(SIGQUIT,newsa,olds[4]);
+  (void) sigaction(SIGHUP,newsa,olds[5]);
+  (void) sigaction(SIGALRM,newsa,olds[6]);
+  (void) free(newsa);
+  }
+else {
+  int i;
+
+  (void) sigaction(SIGALRM,olds[6],(struct sigaction *)0);
+  (void) sigaction(SIGHUP,olds[5],(struct sigaction *)0);
+  (void) sigaction(SIGQUIT,olds[4],(struct sigaction *)0);
+  (void) sigaction(SIGTERM,olds[3],(struct sigaction *)0);
+  (void) sigaction(SIGINT,olds[2],(struct sigaction *)0);
+  (void) sigaction(SIGUSR1,olds[1],(struct sigaction *)0);
+  (void) sigaction(SIGUSR2,olds[0],(struct sigaction *)0);
+  for (i=0;i<NUMINTR;i++) {
+    if (olds[i]!=(struct sigaction *)0) 
+      (void) free(olds[i]);
+    olds[i]=(struct sigaction *)0;
+    }
+  }
+alldone=onoff;
+#undef  OPEP
+}
+/*
+^L
+*/
+/********************************************************/
+/*                                                      */
+/*     Procedure to "open/close" module and do         */
+/*      homework purpose                                */
+/*      return zero if everything right                 */
+/*                                                      */
+/********************************************************/
+int sig_modeunisig(_Bool mode)
+
+{
+#define OPEP    "unisig.c:sig_modeunisig"
+
+int status;
+
+status=0;
+if (mode!=modopen) {
+  switch ((int)mode) {
+    case true     :
+      (void) rou_modesubrou(mode);
+      (void) trapsigsegv(mode,gotsigsegv);
+      break;
+    case false    :
+      (void) trapsigsegv(mode,gotsigsegv);
+      (void) rou_modesubrou(mode);
+      break;
+    default       :
+      (void) fprintf(stderr,"Calling %s with wrong mode='%d' (Bug?!):",
+                            OPEP,(int)mode);
+      status=-1;
+      break;
+    }
+  modopen=mode;
+  }
+return status;
+#undef  OPEP
+}
diff --git a/lib/unisig.h b/lib/unisig.h
new file mode 100644 (file)
index 0000000..61336d4
--- /dev/null
@@ -0,0 +1,32 @@
+// vim: smarttab tabstop=8 shiftwidth=2 expandtab
+/************************************************/
+/*                                             */
+/*     Unit level signal management            */
+/*      declaration                             */
+/*                                             */
+/************************************************/
+#ifndef        UNISIG
+#define UNISIG
+
+#include        <stdbool.h>
+#include        <signal.h>
+
+#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