1 /*
2 * Copyright (C) 2016 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3 *
4 * This file is part of MooseFS.
5 *
6 * MooseFS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 (only).
9 *
10 * MooseFS is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with MooseFS; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18 * or visit http://www.gnu.org/licenses/gpl-2.0.html
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #ifndef MFSMAXFILES
26 #define MFSMAXFILES 4096
27 #endif
28
29 #if defined(HAVE_MLOCKALL)
30 # if defined(HAVE_SYS_MMAN_H)
31 # include <sys/mman.h>
32 # endif
33 # if defined(HAVE_SYS_RESOURCE_H)
34 # include <sys/resource.h>
35 # endif
36 # if defined(RLIMIT_MEMLOCK) && defined(MCL_CURRENT) && defined(MCL_FUTURE)
37 # define MFS_USE_MEMLOCK 1
38 # endif
39 #endif
40
41 #if defined(HAVE_MALLOC_H)
42 # include <malloc.h>
43 #endif
44
45 #if defined(HAVE_SYS_PRCTL_H)
46 # include <sys/prctl.h>
47 #endif
48
49 #include <sys/stat.h>
50 #include <sys/wait.h>
51 #include <sys/types.h>
52 #include <sys/time.h>
53
54 #include <signal.h>
55 #include <fcntl.h>
56 #include <unistd.h>
57 #include <errno.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <syslog.h>
61 #include <string.h>
62 #include <strings.h>
63 #include <time.h>
64 #include <sys/resource.h>
65 #include <grp.h>
66 #include <pwd.h>
67
68 #define STR_AUX(x) #x
69 #define STR(x) STR_AUX(x)
70
71 #include "main.h"
72 #include "clocks.h"
73 #include "sockets.h"
74 #include "cfg.h"
75 #include "strerr.h"
76 #include "crc.h"
77 #include "init.h"
78 #include "massert.h"
79 #include "slogger.h"
80 #include "portable.h"
81
82 #define RM_RESTART 0
83 #define RM_START 1
84 #define RM_STOP 2
85 #define RM_RELOAD 3
86 #define RM_INFO 4
87 #define RM_TEST 5
88 #define RM_KILL 6
89 #define RM_TRY_RESTART 7
90
91 typedef struct deentry {
92 void (*fun)(void);
93 struct deentry *next;
94 } deentry;
95
96 static deentry *dehead=NULL;
97
98
99 typedef struct weentry {
100 void (*fun)(void);
101 struct weentry *next;
102 } weentry;
103
104 static weentry *wehead=NULL;
105
106
107 typedef struct ceentry {
108 int (*fun)(void);
109 struct ceentry *next;
110 } ceentry;
111
112 static ceentry *cehead=NULL;
113
114
115 typedef struct rlentry {
116 void (*fun)(void);
117 struct rlentry *next;
118 } rlentry;
119
120 static rlentry *rlhead=NULL;
121
122
123 typedef struct inentry {
124 void (*fun)(void);
125 struct inentry *next;
126 } inentry;
127
128 static inentry *inhead=NULL;
129
130
131 typedef struct kaentry {
132 void (*fun)(void);
133 struct kaentry *next;
134 } kaentry;
135
136 static kaentry *kahead=NULL;
137
138
139 typedef struct pollentry {
140 void (*desc)(struct pollfd *,uint32_t *);
141 void (*serve)(struct pollfd *);
142 struct pollentry *next;
143 } pollentry;
144
145 static pollentry *pollhead=NULL;
146
147
148 typedef struct eloopentry {
149 void (*fun)(void);
150 struct eloopentry *next;
151 } eloopentry;
152
153 static eloopentry *eloophead=NULL;
154
155
156 typedef struct chldentry {
157 pid_t pid;
158 void (*fun)(int);
159 struct chldentry *next;
160 } chldentry;
161
162 static chldentry *chldhead=NULL;
163
164
165 typedef struct timeentry {
166 uint64_t nextevent;
167 uint64_t useconds;
168 uint64_t usecoffset;
169 void (*fun)(void);
170 struct timeentry *next;
171 } timeentry;
172
173 static timeentry *timehead=NULL;
174
175 static uint32_t now;
176 static uint64_t usecnow;
177 //static int alcnt=0;
178
179 static int signalpipe[2];
180
181 /* interface */
182
main_destruct_register(void (* fun)(void))183 void main_destruct_register (void (*fun)(void)) {
184 deentry *aux=(deentry*)malloc(sizeof(deentry));
185 passert(aux);
186 aux->fun = fun;
187 aux->next = dehead;
188 dehead = aux;
189 }
190
main_canexit_register(int (* fun)(void))191 void main_canexit_register (int (*fun)(void)) {
192 ceentry *aux=(ceentry*)malloc(sizeof(ceentry));
193 passert(aux);
194 aux->fun = fun;
195 aux->next = cehead;
196 cehead = aux;
197 }
198
main_wantexit_register(void (* fun)(void))199 void main_wantexit_register (void (*fun)(void)) {
200 weentry *aux=(weentry*)malloc(sizeof(weentry));
201 passert(aux);
202 aux->fun = fun;
203 aux->next = wehead;
204 wehead = aux;
205 }
206
main_reload_register(void (* fun)(void))207 void main_reload_register (void (*fun)(void)) {
208 rlentry *aux=(rlentry*)malloc(sizeof(rlentry));
209 passert(aux);
210 aux->fun = fun;
211 aux->next = rlhead;
212 rlhead = aux;
213 }
214
main_info_register(void (* fun)(void))215 void main_info_register (void (*fun)(void)) {
216 inentry *aux=(inentry*)malloc(sizeof(inentry));
217 passert(aux);
218 aux->fun = fun;
219 aux->next = inhead;
220 inhead = aux;
221 }
222
main_keepalive_register(void (* fun)(void))223 void main_keepalive_register (void (*fun)(void)) {
224 kaentry *aux=(kaentry*)malloc(sizeof(kaentry));
225 passert(aux);
226 aux->fun = fun;
227 aux->next = kahead;
228 kahead = aux;
229 }
230
main_poll_register(void (* desc)(struct pollfd *,uint32_t *),void (* serve)(struct pollfd *))231 void main_poll_register (void (*desc)(struct pollfd *,uint32_t *),void (*serve)(struct pollfd *)) {
232 pollentry *aux=(pollentry*)malloc(sizeof(pollentry));
233 passert(aux);
234 aux->desc = desc;
235 aux->serve = serve;
236 aux->next = pollhead;
237 pollhead = aux;
238 }
239
main_eachloop_register(void (* fun)(void))240 void main_eachloop_register (void (*fun)(void)) {
241 eloopentry *aux=(eloopentry*)malloc(sizeof(eloopentry));
242 passert(aux);
243 aux->fun = fun;
244 aux->next = eloophead;
245 eloophead = aux;
246 }
247
main_chld_register(pid_t pid,void (* fun)(int))248 void main_chld_register (pid_t pid,void (*fun)(int)) {
249 chldentry *aux=(chldentry*)malloc(sizeof(chldentry));
250 passert(aux);
251 aux->fun = fun;
252 aux->pid = pid;
253 aux->next = chldhead;
254 chldhead = aux;
255 }
256
main_msectime_register(uint32_t mseconds,uint32_t offset,void (* fun)(void))257 void* main_msectime_register (uint32_t mseconds,uint32_t offset,void (*fun)(void)) {
258 timeentry *aux;
259 uint64_t useconds = UINT64_C(1000) * (uint64_t)mseconds;
260 uint64_t usecoffset = UINT64_C(1000) * (uint64_t)offset;
261 if (useconds==0 || usecoffset>=useconds) {
262 return NULL;
263 }
264 aux = (timeentry*)malloc(sizeof(timeentry));
265 passert(aux);
266 aux->nextevent = (((usecnow / useconds) * useconds) + usecoffset);
267 while (aux->nextevent<usecnow) {
268 aux->nextevent+=useconds;
269 }
270 aux->useconds = useconds;
271 aux->usecoffset = usecoffset;
272 aux->fun = fun;
273 aux->next = timehead;
274 timehead = aux;
275 return aux;
276 }
277
main_msectime_change(void * x,uint32_t mseconds,uint32_t offset)278 int main_msectime_change(void* x,uint32_t mseconds,uint32_t offset) {
279 timeentry *aux = (timeentry*)x;
280 uint64_t useconds = UINT64_C(1000) * (uint64_t)mseconds;
281 uint64_t usecoffset = UINT64_C(1000) * (uint64_t)offset;
282 if (useconds==0 || usecoffset>=useconds) {
283 return -1;
284 }
285 aux->nextevent = (((usecnow / useconds) * useconds) + usecoffset);
286 while (aux->nextevent<usecnow) {
287 aux->nextevent+=useconds;
288 }
289 aux->useconds = useconds;
290 aux->usecoffset = usecoffset;
291 return 0;
292 }
293
main_time_register(uint32_t seconds,uint32_t offset,void (* fun)(void))294 void* main_time_register (uint32_t seconds,uint32_t offset,void (*fun)(void)) {
295 return main_msectime_register(1000*seconds,1000*offset,fun);
296 /* timeentry *aux;
297 if (seconds==0 || offset>=seconds) {
298 return NULL;
299 }
300 aux = (timeentry*)malloc(sizeof(timeentry));
301 passert(aux);
302 aux->nextevent = (((now / seconds) * seconds) + offset);
303 while (aux->nextevent<now) {
304 aux->nextevent+=seconds;
305 }
306 aux->seconds = seconds;
307 aux->offset = offset;
308 aux->mode = mode;
309 aux->fun = fun;
310 aux->next = timehead;
311 timehead = aux;
312 return aux;
313 */
314 }
315
main_time_change(void * x,uint32_t seconds,uint32_t offset)316 int main_time_change(void* x,uint32_t seconds,uint32_t offset) {
317 return main_msectime_change(x,1000*seconds,1000*offset);
318 /* timeentry *aux = (timeentry*)x;
319 if (seconds==0 || offset>=seconds) {
320 return -1;
321 }
322 aux->nextevent = ((now / seconds) * seconds) + offset;
323 while (aux->nextevent<now) {
324 aux->nextevent+=seconds;
325 }
326 aux->seconds = seconds;
327 aux->offset = offset;
328 aux->mode = mode;
329 return 0;
330 */
331 }
332
333 /* internal */
334
free_all_registered_entries(void)335 void free_all_registered_entries(void) {
336 deentry *de,*den;
337 ceentry *ce,*cen;
338 weentry *we,*wen;
339 rlentry *re,*ren;
340 inentry *ie,*ien;
341 pollentry *pe,*pen;
342 eloopentry *ee,*een;
343 timeentry *te,*ten;
344
345 for (de = dehead ; de ; de = den) {
346 den = de->next;
347 free(de);
348 }
349
350 for (ce = cehead ; ce ; ce = cen) {
351 cen = ce->next;
352 free(ce);
353 }
354
355 for (we = wehead ; we ; we = wen) {
356 wen = we->next;
357 free(we);
358 }
359
360 for (re = rlhead ; re ; re = ren) {
361 ren = re->next;
362 free(re);
363 }
364
365 for (ie = inhead ; ie ; ie = ien) {
366 ien = ie->next;
367 free(ie);
368 }
369
370 for (pe = pollhead ; pe ; pe = pen) {
371 pen = pe->next;
372 free(pe);
373 }
374
375 for (ee = eloophead ; ee ; ee = een) {
376 een = ee->next;
377 free(ee);
378 }
379
380 for (te = timehead ; te ; te = ten) {
381 ten = te->next;
382 free(te);
383 }
384 }
385
canexit()386 int canexit() {
387 ceentry *aux;
388 for (aux = cehead ; aux!=NULL ; aux=aux->next ) {
389 if (aux->fun()==0) {
390 return 0;
391 }
392 }
393 return 1;
394 }
395
main_time()396 uint32_t main_time() {
397 return now;
398 }
399
400 /*
401 uint64_t main_utime() {
402 return usecnow;
403 }
404 */
destruct(void)405 static inline void destruct(void) {
406 deentry *deit;
407 for (deit = dehead ; deit!=NULL ; deit=deit->next ) {
408 deit->fun();
409 }
410 }
411
main_keep_alive(void)412 void main_keep_alive(void) {
413 struct timeval tv;
414 gettimeofday(&tv,NULL);
415 usecnow = tv.tv_sec;
416 usecnow *= 1000000;
417 usecnow += tv.tv_usec;
418 now = tv.tv_sec;
419 kaentry *kait;
420 for (kait = kahead ; kait!=NULL ; kait=kait->next ) {
421 kait->fun();
422 }
423 }
424
mainloop()425 void mainloop() {
426 uint64_t prevtime = 0;
427 struct timeval tv;
428 pollentry *pollit;
429 eloopentry *eloopit;
430 timeentry *timeit;
431 ceentry *ceit;
432 weentry *weit;
433 rlentry *rlit;
434 inentry *init;
435 struct pollfd pdesc[MFSMAXFILES];
436 uint32_t ndesc;
437 int i;
438 int t,r;
439
440 t = 0;
441 r = 0;
442 while (t!=3) {
443 ndesc=1;
444 pdesc[0].fd = signalpipe[0];
445 pdesc[0].events = POLLIN;
446 pdesc[0].revents = 0;
447 for (pollit = pollhead ; pollit != NULL ; pollit = pollit->next) {
448 pollit->desc(pdesc,&ndesc);
449 }
450 i = poll(pdesc,ndesc,10);
451 gettimeofday(&tv,NULL);
452 usecnow = tv.tv_sec;
453 usecnow *= 1000000;
454 usecnow += tv.tv_usec;
455 now = tv.tv_sec;
456 if (i<0) {
457 if (!ERRNO_ERROR) {
458 syslog(LOG_WARNING,"poll returned EAGAIN");
459 portable_usleep(10000);
460 continue;
461 }
462 if (errno!=EINTR) {
463 syslog(LOG_WARNING,"poll error: %s",strerr(errno));
464 break;
465 }
466 } else {
467 if ((pdesc[0].revents)&POLLIN) {
468 uint8_t sigid;
469 if (read(signalpipe[0],&sigid,1)==1) {
470 if (sigid=='\001' && t==0) {
471 syslog(LOG_NOTICE,"terminate signal received");
472 t = 1;
473 } else if (sigid=='\002') {
474 syslog(LOG_NOTICE,"reloading config files");
475 r = 1;
476 } else if (sigid=='\003') {
477 syslog(LOG_NOTICE,"child finished");
478 r = 2;
479 } else if (sigid=='\004') {
480 syslog(LOG_NOTICE,"log extra info");
481 r = 3;
482 } else if (sigid=='\005') {
483 syslog(LOG_NOTICE,"unexpected alarm/prof signal received - ignoring");
484 } else if (sigid=='\006') {
485 syslog(LOG_NOTICE,"internal terminate request");
486 t = 1;
487 }
488 }
489 }
490 for (pollit = pollhead ; pollit != NULL ; pollit = pollit->next) {
491 pollit->serve(pdesc);
492 }
493 }
494 for (eloopit = eloophead ; eloopit != NULL ; eloopit = eloopit->next) {
495 eloopit->fun();
496 }
497 if (usecnow<prevtime) {
498 // time went backward !!! - recalculate "nextevent" time
499 // adding previous_time_to_run prevents from running next event too soon.
500 for (timeit = timehead ; timeit != NULL ; timeit = timeit->next) {
501 uint64_t previous_time_to_run = timeit->nextevent - prevtime;
502 if (previous_time_to_run > timeit->useconds) {
503 previous_time_to_run = timeit->useconds;
504 }
505 timeit->nextevent = ((usecnow / timeit->useconds) * timeit->useconds) + timeit->usecoffset;
506 while (timeit->nextevent <= usecnow+previous_time_to_run) {
507 timeit->nextevent += timeit->useconds;
508 }
509 }
510 } else if (usecnow>prevtime+UINT64_C(3600000000)) {
511 // time went forward !!! - just recalculate "nextevent" time
512 for (timeit = timehead ; timeit != NULL ; timeit = timeit->next) {
513 timeit->nextevent = ((usecnow / timeit->useconds) * timeit->useconds) + timeit->usecoffset;
514 while (usecnow >= timeit->nextevent) {
515 timeit->nextevent += timeit->useconds;
516 }
517 }
518 }
519 for (timeit = timehead ; timeit != NULL ; timeit = timeit->next) {
520 if (usecnow >= timeit->nextevent) {
521 uint32_t eventcounter = 0;
522 while (usecnow >= timeit->nextevent && eventcounter<10) { // do not run more than 10 late entries
523 timeit->fun();
524 timeit->nextevent += timeit->useconds;
525 eventcounter++;
526 }
527 if (usecnow >= timeit->nextevent) {
528 timeit->nextevent = ((usecnow / timeit->useconds) * timeit->useconds) + timeit->usecoffset;
529 while (usecnow >= timeit->nextevent) {
530 timeit->nextevent += timeit->useconds;
531 }
532 }
533 }
534 }
535 prevtime = usecnow;
536 if (r==2) {
537 chldentry *chldit,**chldptr;
538 pid_t pid;
539 int status;
540
541 while ( (pid = waitpid(-1,&status,WNOHANG)) >= 0) {
542 chldptr = &chldhead;
543 while ((chldit = *chldptr)) {
544 if (chldit->pid == pid) {
545 chldit->fun(status);
546 *chldptr = chldit->next;
547 free(chldit);
548 } else {
549 chldptr = &(chldit->next);
550 }
551 }
552 }
553 r = 0;
554 }
555 if (t==0) {
556 if (r==1) {
557 cfg_reload();
558 for (rlit = rlhead ; rlit!=NULL ; rlit=rlit->next ) {
559 rlit->fun();
560 }
561 r = 0;
562 } else if (r==3) {
563 for (init = inhead ; init!=NULL ; init=init->next ) {
564 init->fun();
565 }
566 r = 0;
567 }
568 }
569 if (t==1) {
570 for (weit = wehead ; weit!=NULL ; weit=weit->next ) {
571 weit->fun();
572 }
573 t = 2;
574 }
575 if (t==2) {
576 i = 1;
577 for (ceit = cehead ; ceit!=NULL && i ; ceit=ceit->next ) {
578 if (ceit->fun()==0) {
579 i=0;
580 }
581 }
582 if (i) {
583 t = 3;
584 }
585 }
586 }
587 }
588
initialize(void)589 int initialize(void) {
590 uint32_t i;
591 int ok;
592 ok = 1;
593 for (i=0 ; (long int)(RunTab[i].fn)!=0 && ok ; i++) {
594 now = time(NULL);
595 if (RunTab[i].fn()<0) {
596 mfs_arg_syslog(LOG_ERR,"init: %s failed !!!",RunTab[i].name);
597 ok=0;
598 }
599 }
600 return ok;
601 }
602
initialize_late(void)603 int initialize_late(void) {
604 uint32_t i;
605 int ok;
606 ok = 1;
607 for (i=0 ; (long int)(LateRunTab[i].fn)!=0 && ok ; i++) {
608 now = time(NULL);
609 if (LateRunTab[i].fn()<0) {
610 mfs_arg_syslog(LOG_ERR,"init: %s failed !!!",RunTab[i].name);
611 ok=0;
612 }
613 }
614 now = time(NULL);
615 return ok;
616 }
617
618
619
620 /* signals */
621
622 static int termsignal[]={
623 SIGTERM,
624 -1
625 };
626
627 static int reloadsignal[]={
628 SIGHUP,
629 -1
630 };
631
632 static int infosignal[]={
633 #ifdef SIGINFO
634 SIGINFO,
635 #endif
636 #ifdef SIGUSR1
637 SIGUSR1,
638 #endif
639 -1
640 };
641
642 static int chldsignal[]={
643 #ifdef SIGCHLD
644 SIGCHLD,
645 #endif
646 #ifdef SIGCLD
647 SIGCLD,
648 #endif
649 -1
650 };
651
652 static int ignoresignal[]={
653 SIGQUIT,
654 #ifdef SIGPIPE
655 SIGPIPE,
656 #endif
657 #ifdef SIGTSTP
658 SIGTSTP,
659 #endif
660 #ifdef SIGTTIN
661 SIGTTIN,
662 #endif
663 #ifdef SIGTTOU
664 SIGTTOU,
665 #endif
666 #ifdef SIGUSR2
667 SIGUSR2,
668 #endif
669 -1
670 };
671
672 static int alarmsignal[]={
673 #ifdef SIGALRM
674 SIGALRM,
675 #endif
676 #ifdef SIGVTALRM
677 SIGVTALRM,
678 #endif
679 #ifdef SIGPROF
680 SIGPROF,
681 #endif
682 -1
683 };
684
685 static int daemonignoresignal[]={
686 SIGINT,
687 -1
688 };
689
termhandle(int signo)690 void termhandle(int signo) {
691 signo = write(signalpipe[1],"\001",1); // killing two birds with one stone - use signo and do something with value returned by write :)
692 (void)signo; // and then use this value to calm down compiler ;)
693 }
694
reloadhandle(int signo)695 void reloadhandle(int signo) {
696 signo = write(signalpipe[1],"\002",1); // see above
697 (void)signo;
698 }
699
chldhandle(int signo)700 void chldhandle(int signo) {
701 signo = write(signalpipe[1],"\003",1); // see above
702 (void)signo;
703 }
704
infohandle(int signo)705 void infohandle(int signo) {
706 signo = write(signalpipe[1],"\004",1); // see above
707 (void)signo;
708 }
709
alarmhandle(int signo)710 void alarmhandle(int signo) {
711 signo = write(signalpipe[1],"\005",1); // see above
712 (void)signo;
713 }
714
set_signal_handlers(int daemonflag)715 void set_signal_handlers(int daemonflag) {
716 struct sigaction sa;
717 uint32_t i;
718
719 zassert(pipe(signalpipe));
720
721 #ifdef SA_RESTART
722 sa.sa_flags = SA_RESTART;
723 #else
724 sa.sa_flags = 0;
725 #endif
726 sigemptyset(&sa.sa_mask);
727
728 sa.sa_handler = termhandle;
729 for (i=0 ; termsignal[i]>0 ; i++) {
730 sigaction(termsignal[i],&sa,(struct sigaction *)0);
731 }
732 sa.sa_handler = reloadhandle;
733 for (i=0 ; reloadsignal[i]>0 ; i++) {
734 sigaction(reloadsignal[i],&sa,(struct sigaction *)0);
735 }
736 sa.sa_handler = infohandle;
737 for (i=0 ; infosignal[i]>0 ; i++) {
738 sigaction(infosignal[i],&sa,(struct sigaction *)0);
739 }
740 sa.sa_handler = alarmhandle;
741 for (i=0 ; alarmsignal[i]>0 ; i++) {
742 sigaction(alarmsignal[i],&sa,(struct sigaction *)0);
743 }
744 sa.sa_handler = chldhandle;
745 for (i=0 ; chldsignal[i]>0 ; i++) {
746 sigaction(chldsignal[i],&sa,(struct sigaction *)0);
747 }
748 sa.sa_handler = SIG_IGN;
749 for (i=0 ; ignoresignal[i]>0 ; i++) {
750 sigaction(ignoresignal[i],&sa,(struct sigaction *)0);
751 }
752 sa.sa_handler = daemonflag?SIG_IGN:termhandle;
753 for (i=0 ; daemonignoresignal[i]>0 ; i++) {
754 sigaction(daemonignoresignal[i],&sa,(struct sigaction *)0);
755 }
756 }
757
758 #ifdef USE_PTHREADS
main_thread_create(pthread_t * th,const pthread_attr_t * attr,void * (* fn)(void *),void * arg)759 int main_thread_create(pthread_t *th,const pthread_attr_t *attr,void *(*fn)(void *),void *arg) {
760 sigset_t oldset;
761 sigset_t newset;
762 uint32_t i;
763 int res;
764
765 sigemptyset(&newset);
766 for (i=0 ; termsignal[i]>0 ; i++) {
767 sigaddset(&newset, termsignal[i]);
768 }
769 for (i=0 ; reloadsignal[i]>0 ; i++) {
770 sigaddset(&newset, reloadsignal[i]);
771 }
772 for (i=0 ; infosignal[i]>0 ; i++) {
773 sigaddset(&newset, infosignal[i]);
774 }
775 for (i=0 ; alarmsignal[i]>0 ; i++) {
776 sigaddset(&newset, alarmsignal[i]);
777 }
778 for (i=0 ; chldsignal[i]>0 ; i++) {
779 sigaddset(&newset, chldsignal[i]);
780 }
781 for (i=0 ; ignoresignal[i]>0 ; i++) {
782 sigaddset(&newset, ignoresignal[i]);
783 }
784 for (i=0 ; daemonignoresignal[i]>0 ; i++) {
785 sigaddset(&newset, daemonignoresignal[i]);
786 }
787 pthread_sigmask(SIG_BLOCK, &newset, &oldset);
788 res = pthread_create(th,attr,fn,arg);
789 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
790 return res;
791 }
792
main_minthread_create(pthread_t * th,uint8_t detached,void * (* fn)(void *),void * arg)793 int main_minthread_create(pthread_t *th,uint8_t detached,void *(*fn)(void *),void *arg) {
794 static pthread_attr_t *thattr = NULL;
795 static uint8_t thattr_detached;
796 if (thattr == NULL) {
797 size_t mystacksize;
798 thattr = malloc(sizeof(pthread_attr_t));
799 passert(thattr);
800 zassert(pthread_attr_init(thattr));
801 #ifdef PTHREAD_STACK_MIN
802 mystacksize = PTHREAD_STACK_MIN;
803 if (mystacksize < 0x100000) {
804 mystacksize = 0x100000;
805 }
806 #else
807 mystacksize = 0x100000;
808 #endif
809 zassert(pthread_attr_setstacksize(thattr,mystacksize));
810 thattr_detached = detached + 1; // make it different
811 }
812 if (detached != thattr_detached) {
813 if (detached) {
814 zassert(pthread_attr_setdetachstate(thattr,PTHREAD_CREATE_DETACHED));
815 } else {
816 zassert(pthread_attr_setdetachstate(thattr,PTHREAD_CREATE_JOINABLE));
817 }
818 thattr_detached = detached;
819 }
820 return main_thread_create(th,thattr,fn,arg);
821 }
822 #endif
823
main_exit(void)824 void main_exit(void) {
825 int i;
826 i = write(signalpipe[1],"\006",1);
827 (void)i;
828 }
829
signal_cleanup(void)830 void signal_cleanup(void) {
831 close(signalpipe[0]);
832 close(signalpipe[1]);
833 }
834
changeugid(void)835 void changeugid(void) {
836 char pwdgrpbuff[16384];
837 struct passwd pwd,*pw;
838 struct group grp,*gr;
839 char *wuser;
840 char *wgroup;
841 uid_t wrk_uid;
842 gid_t wrk_gid;
843 int gidok;
844
845 if (geteuid()==0) {
846 wuser = cfg_getstr("WORKING_USER",DEFAULT_USER);
847 wgroup = cfg_getstr("WORKING_GROUP",DEFAULT_GROUP);
848
849 gidok = 0;
850 wrk_gid = -1;
851 if (wgroup[0]=='#') {
852 wrk_gid = strtol(wgroup+1,NULL,10);
853 gidok = 1;
854 } else if (wgroup[0]) {
855 getgrnam_r(wgroup,&grp,pwdgrpbuff,16384,&gr);
856 if (gr==NULL) {
857 mfs_arg_syslog(LOG_WARNING,"%s: no such group !!!",wgroup);
858 exit(1);
859 } else {
860 wrk_gid = gr->gr_gid;
861 gidok = 1;
862 }
863 }
864
865 if (wuser[0]=='#') {
866 wrk_uid = strtol(wuser+1,NULL,10);
867 if (gidok==0) {
868 getpwuid_r(wrk_uid,&pwd,pwdgrpbuff,16384,&pw);
869 if (pw==NULL) {
870 mfs_arg_syslog(LOG_ERR,"%s: no such user id - can't obtain group id",wuser+1);
871 exit(1);
872 }
873 wrk_gid = pw->pw_gid;
874 }
875 } else {
876 getpwnam_r(wuser,&pwd,pwdgrpbuff,16384,&pw);
877 if (pw==NULL) {
878 mfs_arg_syslog(LOG_ERR,"%s: no such user !!!",wuser);
879 exit(1);
880 }
881 wrk_uid = pw->pw_uid;
882 if (gidok==0) {
883 wrk_gid = pw->pw_gid;
884 }
885 }
886 free(wuser);
887 free(wgroup);
888
889 if (setgid(wrk_gid)<0) {
890 mfs_arg_errlog(LOG_ERR,"can't set gid to %d",(int)wrk_gid);
891 exit(1);
892 } else {
893 syslog(LOG_NOTICE,"set gid to %d",(int)wrk_gid);
894 }
895 if (setuid(wrk_uid)<0) {
896 mfs_arg_errlog(LOG_ERR,"can't set uid to %d",(int)wrk_uid);
897 exit(1);
898 } else {
899 syslog(LOG_NOTICE,"set uid to %d",(int)wrk_uid);
900 }
901 }
902 }
903
904 static int lfd = -1; // main lock
905
mylock(int fd)906 pid_t mylock(int fd) {
907 struct flock fl;
908 fl.l_start = 0;
909 fl.l_len = 0;
910 fl.l_pid = getpid();
911 fl.l_type = F_WRLCK;
912 fl.l_whence = SEEK_SET;
913 for (;;) {
914 if (fcntl(fd,F_SETLK,&fl)>=0) { // lock set
915 return 0; // ok
916 }
917 if (ERRNO_ERROR) { // error other than "already locked"
918 return -1; // error
919 }
920 if (fcntl(fd,F_GETLK,&fl)<0) { // get lock owner
921 return -1; // error getting lock
922 }
923 if (fl.l_type!=F_UNLCK) { // found lock
924 return fl.l_pid; // return lock owner
925 }
926 }
927 return -1; // pro forma
928 }
929
wdunlock(void)930 void wdunlock(void) {
931 if (lfd>=0) {
932 close(lfd);
933 }
934 }
935
wdlock(uint8_t runmode,uint32_t timeout)936 uint8_t wdlock(uint8_t runmode,uint32_t timeout) {
937 pid_t ownerpid;
938 pid_t newownerpid;
939 uint32_t l;
940
941 lfd = open("." STR(APPNAME) ".lock",O_WRONLY|O_CREAT,0666);
942 if (lfd<0) {
943 mfs_errlog(LOG_ERR,"can't create lockfile in working directory");
944 return 1;
945 }
946 ownerpid = mylock(lfd);
947 if (ownerpid<0) {
948 mfs_errlog(LOG_ERR,"fcntl error");
949 return 1;
950 }
951 if (ownerpid>0) {
952 if (runmode==RM_TEST) {
953 fprintf(stderr,STR(APPNAME) " pid: %ld\n",(long)ownerpid);
954 return 0;
955 }
956 if (runmode==RM_START) {
957 fprintf(stderr,"can't start: lockfile is already locked by another process\n");
958 return 1;
959 }
960 if (runmode==RM_RELOAD) {
961 if (kill(ownerpid,SIGHUP)<0) {
962 mfs_errlog(LOG_WARNING,"can't send reload signal to lock owner");
963 return 1;
964 }
965 fprintf(stderr,"reload signal has been sent\n");
966 return 0;
967 }
968 if (runmode==RM_INFO) {
969 #ifdef SIGINFO
970 if (kill(ownerpid,SIGINFO)<0) {
971 #else
972 if (kill(ownerpid,SIGUSR1)<0) {
973 #endif
974 mfs_errlog(LOG_WARNING,"can't send info signal to lock owner");
975 return 1;
976 }
977 fprintf(stderr,"info signal has been sent\n");
978 return 0;
979 }
980 if (runmode==RM_KILL) {
981 fprintf(stderr,"sending SIGKILL to lock owner (pid:%ld)\n",(long int)ownerpid);
982 if (kill(ownerpid,SIGKILL)<0) {
983 mfs_errlog(LOG_WARNING,"can't kill lock owner");
984 return 1;
985 }
986 } else {
987 fprintf(stderr,"sending SIGTERM to lock owner (pid:%ld)\n",(long int)ownerpid);
988 if (kill(ownerpid,SIGTERM)<0) {
989 mfs_errlog(LOG_WARNING,"can't kill lock owner");
990 return 1;
991 }
992 }
993 l=0;
994 fprintf(stderr,"waiting for termination ");
995 fflush(stderr);
996 do {
997 newownerpid = mylock(lfd);
998 if (newownerpid<0) {
999 mfs_errlog(LOG_ERR,"fcntl error");
1000 return 1;
1001 }
1002 if (newownerpid>0) {
1003 l++;
1004 if (l>=timeout) {
1005 syslog(LOG_ERR,"about %"PRIu32" seconds passed and lockfile is still locked - giving up",l);
1006 fprintf(stderr,":giving up\n");
1007 return 1;
1008 }
1009 if (l%10==0) {
1010 syslog(LOG_WARNING,"about %"PRIu32" seconds passed and lock still exists",l);
1011 fprintf(stderr,".");
1012 fflush(stderr);
1013 }
1014 if (newownerpid!=ownerpid) {
1015 fprintf(stderr,"\nnew lock owner detected\n");
1016 if (runmode==RM_KILL) {
1017 fprintf(stderr,":sending SIGKILL to lock owner (pid:%ld):",(long int)newownerpid);
1018 fflush(stderr);
1019 if (kill(newownerpid,SIGKILL)<0) {
1020 mfs_errlog(LOG_WARNING,"can't kill lock owner");
1021 return 1;
1022 }
1023 } else {
1024 fprintf(stderr,":sending SIGTERM to lock owner (pid:%ld):",(long int)newownerpid);
1025 fflush(stderr);
1026 if (kill(newownerpid,SIGTERM)<0) {
1027 mfs_errlog(LOG_WARNING,"can't kill lock owner");
1028 return 1;
1029 }
1030 }
1031 ownerpid = newownerpid;
1032 }
1033 }
1034 sleep(1);
1035 } while (newownerpid!=0);
1036 fprintf(stderr,"terminated\n");
1037 return 0;
1038 }
1039 if (runmode==RM_START || runmode==RM_RESTART) {
1040 char pidstr[20];
1041 l = snprintf(pidstr,20,"%ld\n",(long)(getpid()));
1042 if (ftruncate(lfd,0)<0) {
1043 fprintf(stderr,"can't truncate pidfile\n");
1044 }
1045 if (write(lfd,pidstr,l)!=(ssize_t)l) {
1046 fprintf(stderr,"can't write pid to pidfile\n");
1047 }
1048 fprintf(stderr,"lockfile created and locked\n");
1049 } else if (runmode==RM_TRY_RESTART) {
1050 fprintf(stderr,"can't find process to restart\n");
1051 return 1;
1052 } else if (runmode==RM_STOP || runmode==RM_KILL) {
1053 fprintf(stderr,"can't find process to terminate\n");
1054 return 0;
1055 } else if (runmode==RM_RELOAD) {
1056 fprintf(stderr,"can't find process to send reload signal\n");
1057 return 1;
1058 } else if (runmode==RM_INFO) {
1059 fprintf(stderr,"can't find process to send info signal\n");
1060 return 1;
1061 } else if (runmode==RM_TEST) {
1062 fprintf(stderr,STR(APPNAME) " is not running\n");
1063 return 1;
1064 }
1065 return 0;
1066 }
1067
1068 void makedaemon() {
1069 int f;
1070 uint8_t pipebuff[1000];
1071 ssize_t r;
1072 size_t happy;
1073 int piped[2];
1074
1075 fflush(stdout);
1076 fflush(stderr);
1077 if (pipe(piped)<0) {
1078 fprintf(stderr,"pipe error\n");
1079 exit(1);
1080 }
1081 f = fork();
1082 if (f<0) {
1083 syslog(LOG_ERR,"first fork error: %s",strerr(errno));
1084 exit(1);
1085 }
1086 if (f>0) {
1087 wait(&f); // just get child status - prevents child from being zombie during initialization stage
1088 if (f) {
1089 fprintf(stderr,"Child status: %d\n",f);
1090 exit(1);
1091 }
1092 close(piped[1]);
1093 // printf("Starting daemon ...\n");
1094 while ((r=read(piped[0],pipebuff,1000))) {
1095 if (r>0) {
1096 if (pipebuff[r-1]==0) { // zero as a last char in the pipe means error
1097 if (r>1) {
1098 happy = fwrite(pipebuff,1,r-1,stderr);
1099 (void)happy;
1100 }
1101 exit(1);
1102 }
1103 happy = fwrite(pipebuff,1,r,stderr);
1104 (void)happy;
1105 } else {
1106 fprintf(stderr,"Error reading pipe: %s\n",strerr(errno));
1107 exit(1);
1108 }
1109 }
1110 exit(0);
1111 }
1112 setsid();
1113 setpgid(0,getpid());
1114 f = fork();
1115 if (f<0) {
1116 syslog(LOG_ERR,"second fork error: %s",strerr(errno));
1117 if (write(piped[1],"fork error\n",11)!=11) {
1118 syslog(LOG_ERR,"pipe write error: %s",strerr(errno));
1119 }
1120 close(piped[1]);
1121 exit(1);
1122 }
1123 if (f>0) {
1124 exit(0);
1125 }
1126 set_signal_handlers(1);
1127
1128 close(STDIN_FILENO);
1129 sassert(open("/dev/null", O_RDWR, 0)==STDIN_FILENO);
1130 close(STDOUT_FILENO);
1131 sassert(dup(STDIN_FILENO)==STDOUT_FILENO);
1132 close(STDERR_FILENO);
1133 sassert(dup(piped[1])==STDERR_FILENO);
1134 close(piped[1]);
1135 // setvbuf(stderr,(char *)NULL,_IOLBF,0);
1136 }
1137
1138 void close_msg_channel() {
1139 fflush(stderr);
1140 close(STDERR_FILENO);
1141 sassert(open("/dev/null", O_RDWR, 0)==STDERR_FILENO);
1142 }
1143
1144 void createpath(const char *filename) {
1145 char pathbuff[1024];
1146 const char *src = filename;
1147 char *dst = pathbuff;
1148 if (*src=='/') *dst++=*src++;
1149
1150 while (*src) {
1151 while (*src!='/' && *src) {
1152 *dst++=*src++;
1153 }
1154 if (*src=='/') {
1155 *dst='\0';
1156 if (mkdir(pathbuff,(mode_t)0777)<0) {
1157 if (errno!=EEXIST) {
1158 mfs_arg_errlog(LOG_NOTICE,"creating directory %s",pathbuff);
1159 }
1160 } else {
1161 mfs_arg_syslog(LOG_NOTICE,"directory %s has been created",pathbuff);
1162 }
1163 *dst++=*src++;
1164 }
1165 }
1166 }
1167
1168 void usage(const char *appname) {
1169 printf(
1170 "usage: %s [-vfun] [-t locktimeout] [-c cfgfile] " MODULE_OPTIONS_SYNOPIS "[start|stop|restart|reload|info|test|kill]\n"
1171 "\n"
1172 "-v : print version number and exit\n"
1173 "-f : run in foreground\n"
1174 "-u : log undefined config variables\n"
1175 "-n : do not attempt to increase limit of core dump size\n"
1176 "-t locktimeout : how long wait for lockfile\n"
1177 "-c cfgfile : use given config file\n"
1178 MODULE_OPTIONS_DESC
1179 ,appname);
1180 exit(1);
1181 }
1182
1183 int main(int argc,char **argv) {
1184 char *logappname;
1185 // char *lockfname;
1186 char *wrkdir;
1187 char *cfgfile;
1188 char *ocfgfile;
1189 char *appname;
1190 int ch;
1191 uint8_t runmode;
1192 int rundaemon,logundefined;
1193 int lockmemory;
1194 int forcecoredump;
1195 int32_t nicelevel;
1196 uint32_t locktimeout;
1197 int fd;
1198 uint8_t movewarning;
1199 struct rlimit rls;
1200
1201 strerr_init();
1202 mycrc32_init();
1203
1204 movewarning = 0;
1205 cfgfile=strdup(ETC_PATH "/mfs/" STR(APPNAME) ".cfg");
1206 passert(cfgfile);
1207 if ((fd = open(cfgfile,O_RDONLY))<0 && errno==ENOENT) {
1208 ocfgfile=strdup(ETC_PATH "/" STR(APPNAME) ".cfg");
1209 passert(ocfgfile);
1210 if ((fd = open(ocfgfile,O_RDONLY))>=0) {
1211 free(cfgfile);
1212 cfgfile = ocfgfile;
1213 movewarning = 1;
1214 }
1215 }
1216 if (fd>=0) {
1217 close(fd);
1218 }
1219 locktimeout = 1800;
1220 rundaemon = 1;
1221 runmode = RM_RESTART;
1222 logundefined = 0;
1223 lockmemory = 0;
1224 forcecoredump = 1;
1225 appname = argv[0];
1226
1227 while ((ch = getopt(argc, argv, "nuvfdc:t:h?" MODULE_OPTIONS_GETOPT)) != -1) {
1228 switch(ch) {
1229 case 'v':
1230 printf("version: %s\n",VERSSTR);
1231 return 0;
1232 case 'd':
1233 printf("option '-d' is deprecated - use '-f' instead\n");
1234 // no break on purpose
1235 case 'f':
1236 rundaemon=0;
1237 break;
1238 case 't':
1239 locktimeout=strtoul(optarg,NULL,10);
1240 break;
1241 case 'c':
1242 free(cfgfile);
1243 cfgfile = strdup(optarg);
1244 passert(cfgfile);
1245 movewarning = 0;
1246 break;
1247 case 'u':
1248 logundefined=1;
1249 break;
1250 case 'n':
1251 forcecoredump = 0;
1252 break;
1253 MODULE_OPTIONS_SWITCH
1254 default:
1255 usage(appname);
1256 return 1;
1257 }
1258 }
1259 argc -= optind;
1260 argv += optind;
1261 if (argc==1) {
1262 if (strcasecmp(argv[0],"start")==0) {
1263 runmode = RM_START;
1264 } else if (strcasecmp(argv[0],"stop")==0) {
1265 runmode = RM_STOP;
1266 } else if (strcasecmp(argv[0],"restart")==0) {
1267 runmode = RM_RESTART;
1268 } else if (strcasecmp(argv[0],"try-restart")==0) {
1269 runmode = RM_TRY_RESTART;
1270 } else if (strcasecmp(argv[0],"reload")==0) {
1271 runmode = RM_RELOAD;
1272 } else if (strcasecmp(argv[0],"info")==0) {
1273 runmode = RM_INFO;
1274 } else if (strcasecmp(argv[0],"test")==0 || strcasecmp(argv[0],"status")==0) {
1275 runmode = RM_TEST;
1276 } else if (strcasecmp(argv[0],"kill")==0) {
1277 runmode = RM_KILL;
1278 } else {
1279 usage(appname);
1280 return 1;
1281 }
1282 } else if (argc!=0) {
1283 usage(appname);
1284 return 1;
1285 }
1286
1287 if (movewarning) {
1288 mfs_syslog(LOG_WARNING,"default sysconf path has changed - please move " STR(APPNAME) ".cfg from "ETC_PATH"/ to "ETC_PATH"/mfs/");
1289 }
1290
1291 if (runmode==RM_START || runmode==RM_RESTART || runmode==RM_TRY_RESTART) {
1292 if (rundaemon) {
1293 makedaemon();
1294 } else {
1295 set_signal_handlers(0);
1296 }
1297 }
1298
1299 if (cfg_load(cfgfile,logundefined)==0) {
1300 fprintf(stderr,"can't load config file: %s - using defaults\n",cfgfile);
1301 }
1302 free(cfgfile);
1303
1304 logappname = cfg_getstr("SYSLOG_IDENT",STR(APPNAME));
1305
1306 if (rundaemon) {
1307 if (logappname[0]) {
1308 openlog(logappname, LOG_PID | LOG_NDELAY , LOG_DAEMON);
1309 } else {
1310 openlog(STR(APPNAME), LOG_PID | LOG_NDELAY , LOG_DAEMON);
1311 }
1312 } else {
1313 #if defined(LOG_PERROR)
1314 if (logappname[0]) {
1315 openlog(logappname, LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_USER);
1316 } else {
1317 openlog(STR(APPNAME), LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_USER);
1318 }
1319 #else
1320 if (logappname[0]) {
1321 openlog(logappname, LOG_PID | LOG_NDELAY, LOG_USER);
1322 } else {
1323 openlog(STR(APPNAME), LOG_PID | LOG_NDELAY, LOG_USER);
1324 }
1325 #endif
1326 }
1327
1328 if (runmode==RM_START || runmode==RM_RESTART || runmode==RM_TRY_RESTART) {
1329 rls.rlim_cur = MFSMAXFILES;
1330 rls.rlim_max = MFSMAXFILES;
1331 if (setrlimit(RLIMIT_NOFILE,&rls)<0) {
1332 syslog(LOG_NOTICE,"can't change open files limit to: %u (trying to set smaller value)",MFSMAXFILES);
1333 if (getrlimit(RLIMIT_NOFILE,&rls)>=0) {
1334 uint32_t limit;
1335 if (rls.rlim_max > MFSMAXFILES) {
1336 limit = MFSMAXFILES;
1337 } else {
1338 limit = rls.rlim_max;
1339 }
1340 while (limit>1024) {
1341 rls.rlim_cur = limit;
1342 if (setrlimit(RLIMIT_NOFILE,&rls)>=0) {
1343 mfs_arg_syslog(LOG_NOTICE,"open files limit has been set to: %"PRIu32,limit);
1344 break;
1345 }
1346 limit *= 3;
1347 limit /= 4;
1348 }
1349 }
1350 } else {
1351 mfs_arg_syslog(LOG_NOTICE,"open files limit has been set to: %u",MFSMAXFILES);
1352 }
1353
1354 lockmemory = cfg_getnum("LOCK_MEMORY",0);
1355 #ifdef MFS_USE_MEMLOCK
1356 if (lockmemory) {
1357 rls.rlim_cur = RLIM_INFINITY;
1358 rls.rlim_max = RLIM_INFINITY;
1359 setrlimit(RLIMIT_MEMLOCK,&rls);
1360 }
1361 #endif
1362 nicelevel = cfg_getint32("NICE_LEVEL",-19);
1363 setpriority(PRIO_PROCESS,getpid(),nicelevel);
1364 }
1365
1366 changeugid();
1367
1368 wrkdir = cfg_getstr("DATA_PATH",DATA_PATH);
1369 if (runmode==RM_START || runmode==RM_RESTART || runmode==RM_TRY_RESTART) {
1370 fprintf(stderr,"working directory: %s\n",wrkdir);
1371 }
1372
1373 if (chdir(wrkdir)<0) {
1374 mfs_arg_syslog(LOG_ERR,"can't set working directory to %s",wrkdir);
1375 if (rundaemon) {
1376 fputc(0,stderr);
1377 close_msg_channel();
1378 }
1379 closelog();
1380 free(logappname);
1381 return 1;
1382 }
1383 free(wrkdir);
1384
1385 umask(cfg_getuint32("FILE_UMASK",027)&077);
1386
1387 ch = wdlock(runmode,locktimeout);
1388 if (ch) {
1389 if (rundaemon) {
1390 fputc(0,stderr);
1391 close_msg_channel();
1392 }
1393 closelog();
1394 free(logappname);
1395 wdunlock();
1396 return ch;
1397 }
1398
1399 if (runmode==RM_STOP || runmode==RM_KILL || runmode==RM_RELOAD || runmode==RM_INFO || runmode==RM_TEST) {
1400 if (rundaemon) {
1401 close_msg_channel();
1402 }
1403 closelog();
1404 free(logappname);
1405 wdunlock();
1406 return 0;
1407 }
1408
1409 #ifdef MFS_USE_MEMLOCK
1410 if (lockmemory) {
1411 if (getrlimit(RLIMIT_MEMLOCK,&rls)<0) {
1412 mfs_errlog(LOG_WARNING,"error getting memory lock limits");
1413 } else {
1414 if (rls.rlim_cur!=RLIM_INFINITY && rls.rlim_max==RLIM_INFINITY) {
1415 rls.rlim_cur = RLIM_INFINITY;
1416 rls.rlim_max = RLIM_INFINITY;
1417 if (setrlimit(RLIMIT_MEMLOCK,&rls)<0) {
1418 mfs_errlog(LOG_WARNING,"error setting memory lock limit to unlimited");
1419 }
1420 }
1421 if (getrlimit(RLIMIT_MEMLOCK,&rls)<0) {
1422 mfs_errlog(LOG_WARNING,"error getting memory lock limits");
1423 } else {
1424 if (rls.rlim_cur!=RLIM_INFINITY) {
1425 mfs_errlog(LOG_WARNING,"can't set memory lock limit to unlimited");
1426 } else {
1427 if (mlockall(MCL_CURRENT|MCL_FUTURE)<0) {
1428 mfs_errlog(LOG_WARNING,"memory lock error");
1429 } else {
1430 mfs_syslog(LOG_NOTICE,"process memory was successfully locked in RAM");
1431 }
1432 } }
1433 }
1434 }
1435 #else
1436 if (lockmemory) {
1437 mfs_syslog(LOG_WARNING,"memory lock not supported !!!");
1438 }
1439 #endif
1440
1441 if (forcecoredump) {
1442 rls.rlim_cur = RLIM_INFINITY;
1443 rls.rlim_max = RLIM_INFINITY;
1444 setrlimit(RLIMIT_CORE,&rls);
1445 #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
1446 prctl(PR_SET_DUMPABLE,1);
1447 #endif
1448 }
1449
1450 /* glibc malloc tuning */
1451 #if defined(USE_PTHREADS) && defined(M_ARENA_MAX) && defined(M_ARENA_TEST) && defined(HAVE_MALLOPT)
1452 if (cfg_getuint8("CHANGE_GLIBC_MALLOC_ARENAS",1)==1) {
1453 if (!getenv("MALLOC_ARENA_MAX")) {
1454 mfs_syslog(LOG_NOTICE,"setting glibc malloc arena max to 8");
1455 mallopt(M_ARENA_MAX, 8);
1456 }
1457 if (!getenv("MALLOC_ARENA_TEST")) {
1458 mfs_syslog(LOG_NOTICE,"setting glibc malloc arena test to 1");
1459 mallopt(M_ARENA_TEST, 1);
1460 }
1461 } else {
1462 mfs_syslog(LOG_NOTICE,"setting glibc malloc arenas turned off");
1463 }
1464 #endif /* glibc malloc tuning */
1465
1466 syslog(LOG_NOTICE,"monotonic clock function: %s",monotonic_method());
1467 syslog(LOG_NOTICE,"monotonic clock speed: %"PRIu32" ops / 10 mili seconds",monotonic_speed());
1468
1469 fprintf(stderr,"initializing %s modules ...\n",logappname);
1470
1471 if (initialize()) {
1472 // if (getrlimit(RLIMIT_NOFILE,&rls)==0) {
1473 // syslog(LOG_NOTICE,"open files limit: %lu",(unsigned long)(rls.rlim_cur));
1474 // }
1475 fprintf(stderr,"%s daemon initialized properly\n",logappname);
1476 if (rundaemon) {
1477 close_msg_channel();
1478 }
1479 if (initialize_late()) {
1480 mainloop();
1481 mfs_syslog(LOG_NOTICE,"exited from main loop");
1482 ch=0;
1483 } else {
1484 ch=1;
1485 }
1486 } else {
1487 fprintf(stderr,"error occurred during initialization - exiting\n");
1488 if (rundaemon) {
1489 fputc(0,stderr);
1490 close_msg_channel();
1491 }
1492 ch=1;
1493 }
1494 mfs_syslog(LOG_NOTICE,"exititng ...");
1495 destruct();
1496 free_all_registered_entries();
1497 signal_cleanup();
1498 cfg_term();
1499 strerr_term();
1500 closelog();
1501 free(logappname);
1502 wdunlock();
1503 mfs_arg_syslog(LOG_NOTICE,"process exited successfully (status:%d)",ch);
1504 return ch;
1505 }
1506