#include "subrou.h"
#include "unipar.h"
#include "uniprc.h"
+#include "unisig.h"
#include "modrec.h"
//port listening format is "IP:PORT NUMBER:num iteration"
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;
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
pidlst[i]=(pid_t)0;
}
if (stillrun>0) {
+ (void) prc_nozombie();
(void) sleep(2);
phase--; //let send signal again
}
(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);
#--------------------------------------------------------------------
OBJS= \
modrec.o \
- unipar.o uniprc.o \
+ unipar.o uniprc.o unisig.o \
subrou.o
objs : $(OBJS)
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
/* */
/********************************************************/
#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
/* */
/********************************************************/
//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());
}
/*
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;
#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);
/* 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
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
*/
/********************************************************/
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
*/
/********************************************************/
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);
//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);
int prc_modeuniprc(_Bool mode)
{
-#define OPEP "unipar.c:uni_modeuniprc"
+#define OPEP "unipar.c:prc_modeuniprc"
int status;
//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
--- /dev/null
+// 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
+}
--- /dev/null
+// 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