1 /************************************************/
4 /* Jean-Marc Pigeon <jmp@safe.ca> 2009 */
6 /************************************************/
7 /* This program is free software; you can */
8 /* redistribute it and/or modify it under the */
9 /* terms of the GNU General Public License as */
10 /* published by the Free Software Foundation */
11 /* version 2 of the License */
13 /* This program is distributed in the hope that */
14 /* it will be useful, but WITHOUT ANY WARRANTY; */
15 /* without even the implied warranty of */
16 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR */
17 /* PURPOSE. See the GNU General Public License */
18 /* for more details. */
20 /* You should have received a copy of the GNU */
21 /* General Public License along with this */
22 /* program; if not, write to the Free Software */
23 /* Foundation, Inc., 51 Franklin Street, */
24 /* Fifth Floor, Boston, MA 02110-1301, USA. */
25 /************************************************/
27 /* Implement very sub level procedure to */
28 /* handle process sub function. */
30 /************************************************/
31 #include <sys/resource.h>
32 #include <sys/prctl.h>
48 /************************************************/
50 /* Procedure to catch signal and do what is*/
53 /************************************************/
54 static void trpsignal(int sig)
61 (void) fprintf(stderr,"utlprc.c:trpalrm, Unexpected signal <%s> received",
63 (void) fflush(stderr);
70 /************************************************/
72 /* Procedure to display an core_dump */
73 /* message and terminate application */
75 /************************************************/
76 void prc_core_dump(char *crashdir,char *temps,const char *fmt,va_list args)
82 struct rlimit limites;
85 if (getrlimit(RLIMIT_CORE,&limites)<0) {
86 (void) fprintf(stderr,"getrlimit error='%s'",strerror(errno));
88 limites.rlim_cur=limites.rlim_max;
89 if (setrlimit(RLIMIT_CORE,&limites)<0) {
90 (void) fprintf(stderr,"setrlimit error='%s'",strerror(errno));
92 (void) prctl(PR_SET_DUMPABLE,1,0,0,0);/*to allow core-dump */
93 if (chdir(crashdir)<0) {
97 (void) snprintf(dirdump,sizeof(dirdump),"%s/coredump/","/tmp");
98 (void) snprintf(command,sizeof(command),"mkdir -p %s",dirdump);
99 (void) system(command);
100 if (chdir(dirdump)<0) {
105 if (temps!=(char *)0)
106 (void) fprintf(stderr,"%s ",temps);
107 (void) vfprintf(stderr,fmt,ap);
108 (void) fprintf(stderr,"\n");
109 (void) fprintf(stderr,"going to CORE DUMP (in %score.%d)\n",
111 (void) fflush(stderr);
112 (void) sleep(5); /*to avoid crash avalanche */
113 (void) abort(); /*doing the abort */
114 (void) exit(-1); /*Theoriticaly unreachable */
119 /************************************************/
121 /* Procedure to check if a child process */
122 /* is still alive. */
124 /************************************************/
125 int prc_checkprocess(pid_t pid)
132 case (pid_t)0 : /*0 means no process */
135 case (pid_t)1 : /*init process always OK*/
138 default : /*standard process */
139 if (kill(pid,SIGCHECK)==0)
148 /************************************************/
150 /* Procedure to allow exited child process */
151 /* to leave the zombie stat. */
153 /************************************************/
157 while (waitpid(-1,(int *)0,WNOHANG)>0);
162 /************************************************/
164 /* Procedure to add a process number to */
167 /************************************************/
168 PRCTYP *prc_addtoprc(PRCTYP *plst,pid_t pid)
174 if (plst==(PRCTYP *)0) {
175 plst=(PRCTYP *)calloc(1,sizeof(PRCTYP));
176 plst->pqueue=(pid_t *)calloc(taille,sizeof(pid_t));
178 plst->pqueue[plst->nbr]=pid;
181 plst->pqueue=(pid_t *)realloc((void *)plst->pqueue,taille*sizeof(pid_t));
187 /************************************************/
189 /* Procedure to terminate all child process*/
190 /* refered in a process list. if not */
191 /* successful 'delay' after SIGTERM try, */
192 /* a SIGKILL signal is applied. */
194 /************************************************/
195 PRCTYP *prc_childkill(PRCTYP *prclst,int delay)
198 if (prclst!=(PRCTYP *)0) {
205 (void) prc_nozombie();
206 for (i=0;i<prclst->nbr;i++) {
207 if (pid[i]<=1) /*no way to kill admin process */
209 if (kill(pid[i],SIGTERM)==0)
212 while (overkill==true) {
213 struct timespec timer;
218 while (nanosleep(&timer,&timer)!=0);
219 (void) prc_nozombie();
220 for (i=0;i<prclst->nbr;i++) {
221 if (pid[i]<=1) /*no way to kill admin process */
223 if (kill(pid[i],SIGCHECK)==0)
230 if (overkill==true) {
231 for (i=0;i<prclst->nbr;i++) {
232 if (pid[i]<=1) /*no way to kill admin process */
234 if (kill(pid[i],SIGCHECK)==0) {
235 /*lets kill for sure */
236 (void) kill(pid[i],SIGKILL);
237 (void) fprintf(stderr,"prc_childkill, overkilled process'%05d'\n",
239 (void) fflush(stderr);
243 (void) prc_nozombie();
253 /************************************************/
255 /* Procedure to check exited process among */
256 /* a process list, return only process */
257 /* nomber still up and running. */
259 /************************************************/
260 PRCTYP *prc_childcheck(PRCTYP *prclst)
266 if (prclst!=(PRCTYP *)0) {
270 (void) prc_nozombie();
271 for (i=0;i<prclst->nbr;i++) {
272 if (prc_checkprocess(prclst->pqueue[i])==true) {
273 newprc=prc_addtoprc(newprc,prclst->pqueue[i]);
277 if (prclst->pqueue!=(pid_t *)0)
278 (void) free(prclst->pqueue);
286 /************************************************/
288 /* Procedure to start or stop a 'Pacemaker'*/
289 /* within the application. */
291 /************************************************/
292 void prc_setpace(unsigned long millisec,int onoff)
295 int static done=false;
296 struct sigaction oldsa;
300 struct sigaction newsa;
301 struct itimerval period;
304 newsa.sa_handler=trpsignal;
305 (void) sigemptyset(&newsa.sa_mask);
306 (void) sigaction(SIGALRM,&newsa,&oldsa);
307 period.it_value.tv_sec=millisec/1000;
308 period.it_value.tv_usec=millisec*1000;
309 period.it_interval.tv_sec=period.it_value.tv_sec;
310 period.it_interval.tv_usec=period.it_value.tv_usec;
311 (void) setitimer(ITIMER_REAL,&period,(struct itimerval *)0);
317 struct itimerval period;
319 period.it_value.tv_sec=0;
320 period.it_value.tv_usec=0;
321 period.it_interval.tv_sec=period.it_value.tv_sec;
322 period.it_interval.tv_usec=period.it_value.tv_usec;
323 (void) setitimer(ITIMER_REAL,&period,(struct itimerval *)0);
324 (void) sigaction(SIGALRM,&oldsa,(struct sigaction *)0);