]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/receiver.cc
Merge pull request #965 from zeha/remove-unused-vars
[thirdparty/pdns.git] / pdns / receiver.cc
CommitLineData
12c86877
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
ce19a815 3 Copyright (C) 2002 - 2013 PowerDNS.COM BV
12c86877
BH
4
5 This program is free software; you can redistribute it and/or modify
22dc646a
BH
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
ea44d9d3 8
12c86877
BH
9
10 This program 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 this program; if not, write to the Free Software
06bd9ccf 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12c86877 18*/
e8d78143 19#include "packetcache.hh"
da44c9ea 20
12c86877
BH
21#include <cstdio>
22#include <signal.h>
23#include <cstring>
24#include <cstdlib>
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <netinet/in.h>
28#include <arpa/inet.h>
29#include <iostream>
30#include <string>
31#include <sys/stat.h>
32#include <unistd.h>
33#include <sys/time.h>
34#include <sys/types.h>
35#include <sys/wait.h>
36#include <errno.h>
37#include <pthread.h>
38#include <unistd.h>
39#include <sys/mman.h>
40#include <fcntl.h>
41#include <fstream>
040712e0 42#include <boost/algorithm/string.hpp>
12c86877
BH
43
44#include "config.h"
45#include "dns.hh"
46#include "dnsbackend.hh"
47#include "ueberbackend.hh"
48#include "dnspacket.hh"
49#include "nameserver.hh"
50#include "distributor.hh"
51#include "logger.hh"
52#include "arguments.hh"
53#include "packethandler.hh"
54#include "statbag.hh"
55#include "tcpreceiver.hh"
12c86877
BH
56#include "ws.hh"
57#include "misc.hh"
58#include "dynlistener.hh"
59#include "dynhandler.hh"
60#include "communicator.hh"
61#include "dnsproxy.hh"
731f58b8 62#include "utility.hh"
12c86877 63#include "common_startup.hh"
02116dff 64#include "dnsrecords.hh"
ba1a571d 65#include "version.hh"
12c86877 66
040712e0 67
12c86877
BH
68time_t s_starttime;
69
70string s_programname="pdns"; // used in packethandler.cc
71
c4ac5865 72const char *funnytext=
12c86877
BH
73"*****************************************************************************\n"\
74"Ok, you just ran pdns_server through 'strings' hoping to find funny messages.\n"\
75"Well, you found one. \n"\
76"Two ions are flying through their particle accelerator, says the one to the\n"
77"other 'I think I've lost an electron!' \n"\
78"So the other one says, 'Are you sure?'. 'YEAH! I'M POSITIVE!'\n"\
79" the pdns crew - pdns@powerdns.com\n"
80"*****************************************************************************\n";
81
82
83// start (sys)logging
84
85/** \var Logger L
86\brief All logging is done via L, a Logger instance
87*/
88
89
90/**
91\file receiver.cc
92\brief The main loop of powerdns
93
94This file is where it all happens - main is here, as are the two pivotal threads qthread() and athread()
95*/
96
97void daemonize(void)
98{
99 if(fork())
100 exit(0); // bye bye
101
102 setsid();
103
dd8b6bd1 104 int i=open("/dev/null",O_RDWR); /* open stdin */
11a2091b
BH
105 if(i < 0)
106 L<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl;
107 else {
108 dup2(i,0); /* stdin */
109 dup2(i,1); /* stderr */
110 dup2(i,2); /* stderr */
111 close(i);
112 }
12c86877
BH
113}
114
12c86877 115static int cpid;
12c86877
BH
116static void takedown(int i)
117{
118 if(cpid) {
119 L<<Logger::Error<<"Guardian is killed, taking down children with us"<<endl;
120 kill(cpid,SIGKILL);
93d8ebf9 121 exit(0);
12c86877
BH
122 }
123}
124
125static void writePid(void)
126{
e8d78143 127 string fname=::arg()["socket-dir"]+"/"+s_programname+".pid";
12c86877
BH
128 ofstream of(fname.c_str());
129 if(of)
130 of<<getpid()<<endl;
131 else
132 L<<Logger::Error<<"Requested to write pid for "<<getpid()<<" to "<<fname<<" failed: "<<strerror(errno)<<endl;
133}
134
aced0e6c
BH
135int g_fd1[2], g_fd2[2];
136FILE *g_fp;
137pthread_mutex_t g_guardian_lock = PTHREAD_MUTEX_INITIALIZER;
12c86877 138
64bcb6be
RA
139// The next two methods are not in dynhandler.cc because they use a few items declared in this file.
140static string DLCycleHandler(const vector<string>&parts, pid_t ppid)
141{
142 kill(cpid, SIGKILL); // why?
143 kill(cpid, SIGKILL); // why?
144 sleep(1);
145 return "ok";
146}
147
12c86877
BH
148static string DLRestHandler(const vector<string>&parts, pid_t ppid)
149{
150 string line;
151
152 for(vector<string>::const_iterator i=parts.begin();i!=parts.end();++i) {
153 if(i!=parts.begin())
154 line.append(1,' ');
155 line.append(*i);
156 }
157 line.append(1,'\n');
158
aced0e6c
BH
159 Lock l(&g_guardian_lock);
160
161 try {
162 writen2(g_fd1[1],line.c_str(),line.size()+1);
163 }
3f81d239 164 catch(PDNSException &ae) {
aced0e6c
BH
165 return "Error communicating with instance: "+ae.reason;
166 }
12c86877 167 char mesg[512];
20ca8e7d 168 string response;
aced0e6c 169 while(fgets(mesg,sizeof(mesg),g_fp)) {
188b28bd 170 if(*mesg=='\0')
20ca8e7d
BH
171 break;
172 response+=mesg;
173 }
040712e0 174 boost::trim_right(response);
20ca8e7d 175 return response;
12c86877
BH
176}
177
64bcb6be 178
12c86877
BH
179
180static int guardian(int argc, char **argv)
181{
182 if(isGuarded(argv))
183 return 0;
184
185 int infd=0, outfd=1;
186
187 DynListener dlg(s_programname);
3c90953e
PD
188 dlg.registerFunc("QUIT",&DLQuitHandler, "quit daemon");
189 dlg.registerFunc("CYCLE",&DLCycleHandler, "restart instance");
190 dlg.registerFunc("PING",&DLPingHandler, "ping guardian");
191 dlg.registerFunc("STATUS",&DLStatusHandler, "get instance status from guardian");
12c86877
BH
192 dlg.registerRestFunc(&DLRestHandler);
193 dlg.go();
194 string progname=argv[0];
195
196 bool first=true;
197 cpid=0;
198
aced0e6c
BH
199 pthread_mutex_lock(&g_guardian_lock);
200
12c86877
BH
201 for(;;) {
202 int pid;
203 setStatus("Launching child");
aced0e6c
BH
204
205 if(pipe(g_fd1)<0 || pipe(g_fd2)<0) {
12c86877
BH
206 L<<Logger::Critical<<"Unable to open pipe for coprocess: "<<strerror(errno)<<endl;
207 exit(1);
208 }
209
aced0e6c
BH
210 if(!(g_fp=fdopen(g_fd2[0],"r"))) {
211 L<<Logger::Critical<<"Unable to associate a file pointer with pipe: "<<stringerror()<<endl;
212 exit(1);
213 }
214 setbuf(g_fp,0); // no buffering please, confuses select
215
12c86877
BH
216 if(!(pid=fork())) { // child
217 signal(SIGTERM, SIG_DFL);
218
219 signal(SIGHUP, SIG_DFL);
220 signal(SIGUSR1, SIG_DFL);
221 signal(SIGUSR2, SIG_DFL);
222
223 char **const newargv=new char*[argc+2];
224 int n;
225
e8d78143 226 if(::arg()["config-name"]!="") {
4957a608
BH
227 progname+="-"+::arg()["config-name"];
228 L<<Logger::Error<<"Virtual configuration name: "<<::arg()["config-name"]<<endl;
12c86877
BH
229 }
230
231 newargv[0]=strdup(const_cast<char *>((progname+"-instance").c_str()));
232 for(n=1;n<argc;n++) {
4957a608 233 newargv[n]=argv[n];
12c86877
BH
234 }
235 newargv[n]=0;
236
237 L<<Logger::Error<<"Guardian is launching an instance"<<endl;
aced0e6c
BH
238 close(g_fd1[1]);
239 fclose(g_fp); // this closes g_fd2[0] for us
12c86877 240
aced0e6c 241 if(g_fd1[0]!= infd) {
4957a608
BH
242 dup2(g_fd1[0], infd);
243 close(g_fd1[0]);
12c86877
BH
244 }
245
aced0e6c 246 if(g_fd2[1]!= outfd) {
4957a608
BH
247 dup2(g_fd2[1], outfd);
248 close(g_fd2[1]);
12c86877 249 }
c1663439 250 if(execvp(argv[0], newargv)<0) {
4957a608
BH
251 L<<Logger::Error<<"Unable to execvp '"<<argv[0]<<"': "<<strerror(errno)<<endl;
252 char **p=newargv;
253 while(*p)
254 L<<Logger::Error<<*p++<<endl;
12c86877 255
4957a608 256 exit(1);
12c86877 257 }
c1663439 258 L<<Logger::Error<<"execvp returned!!"<<endl;
12c86877
BH
259 // never reached
260 }
261 else if(pid>0) { // parent
aced0e6c
BH
262 close(g_fd1[0]);
263 close(g_fd2[1]);
12c86877
BH
264
265 if(first) {
4957a608
BH
266 first=false;
267 signal(SIGTERM, takedown);
12c86877 268
4957a608
BH
269 signal(SIGHUP, SIG_IGN);
270 signal(SIGUSR1, SIG_IGN);
271 signal(SIGUSR2, SIG_IGN);
12c86877 272
4957a608 273 writePid();
12c86877 274 }
aced0e6c 275 pthread_mutex_unlock(&g_guardian_lock);
12c86877
BH
276 int status;
277 cpid=pid;
278 for(;;) {
4957a608
BH
279 int ret=waitpid(pid,&status,WNOHANG);
280
281 if(ret<0) {
282 L<<Logger::Error<<"In guardian loop, waitpid returned error: "<<strerror(errno)<<endl;
283 L<<Logger::Error<<"Dying"<<endl;
284 exit(1);
285 }
286 else if(ret) // something exited
287 break;
288 else { // child is alive
289 // execute some kind of ping here
290 if(DLQuitPlease())
291 takedown(1); // needs a parameter..
292 setStatus("Child running on pid "+itoa(pid));
293 sleep(1);
294 }
12c86877 295 }
aced0e6c
BH
296
297 pthread_mutex_lock(&g_guardian_lock);
298 close(g_fd1[1]);
299 fclose(g_fp);
300 g_fp=0;
12c86877
BH
301
302 if(WIFEXITED(status)) {
4957a608
BH
303 int ret=WEXITSTATUS(status);
304
305 if(ret==99) {
306 L<<Logger::Error<<"Child requested a stop, exiting"<<endl;
307 exit(1);
308 }
309 setStatus("Child died with code "+itoa(ret));
310 L<<Logger::Error<<"Our pdns instance exited with code "<<ret<<endl;
311 L<<Logger::Error<<"Respawning"<<endl;
312
313 sleep(1);
314 continue;
12c86877
BH
315 }
316 if(WIFSIGNALED(status)) {
4957a608
BH
317 int sig=WTERMSIG(status);
318 setStatus("Child died because of signal "+itoa(sig));
319 L<<Logger::Error<<"Our pdns instance ("<<pid<<") exited after signal "<<sig<<endl;
12c86877 320#ifdef WCOREDUMP
4957a608
BH
321 if(WCOREDUMP(status))
322 L<<Logger::Error<<"Dumped core"<<endl;
12c86877
BH
323#endif
324
4957a608
BH
325 L<<Logger::Error<<"Respawning"<<endl;
326 sleep(1);
327 continue;
12c86877
BH
328 }
329 L<<Logger::Error<<"No clue what happened! Respawning"<<endl;
330 }
331 else {
332 L<<Logger::Error<<"Unable to fork: "<<strerror(errno)<<endl;
333 exit(1);
334 }
335 }
336}
337
338static void UNIX_declareArguments()
339{
65efcdbc 340 ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=SYSCONFDIR;
e8d78143
BH
341 ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
342 ::arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
343 ::arg().set("module-dir","Default directory for modules")=LIBDIR;
344 ::arg().set("chroot","If set, chroot to this directory for more security")="";
345 ::arg().set("logging-facility","Log under a specific facility")="";
346 ::arg().set("daemon","Operate as a daemon")="no";
12c86877
BH
347
348}
349
350static void loadModules()
351{
e8d78143 352 if(!::arg()["load-modules"].empty()) {
12c86877
BH
353 vector<string>modules;
354
e8d78143 355 stringtok(modules,::arg()["load-modules"],",");
12c86877
BH
356
357 for(vector<string>::const_iterator i=modules.begin();i!=modules.end();++i) {
358 bool res;
359 const string &module=*i;
360
361 if(module.find(".")==string::npos)
4957a608 362 res=UeberBackend::loadmodule(::arg()["module-dir"]+"/lib"+module+"backend.so");
12c86877 363 else if(module[0]=='/' || (module[0]=='.' && module[1]=='/') || (module[0]=='.' && module[1]=='.')) // absolute or current path
4957a608 364 res=UeberBackend::loadmodule(module);
12c86877 365 else
4957a608 366 res=UeberBackend::loadmodule(::arg()["module-dir"]+"/"+module);
12c86877
BH
367
368 if(res==false) {
4957a608
BH
369 L<<Logger::Error<<"receiver unable to load module "<<module<<endl;
370 exit(1);
12c86877
BH
371 }
372 }
373 }
374}
375
12c86877
BH
376#ifdef __linux__
377#include <execinfo.h>
378static void tbhandler(int num)
379{
380 L<<Logger::Critical<<"Got a signal "<<num<<", attempting to print trace: "<<endl;
381 void *array[20]; //only care about last 17 functions (3 taken with tracing support)
382 size_t size;
383 char **strings;
384 size_t i;
385
386 size = backtrace (array, 20);
387 strings = backtrace_symbols (array, size); //Need -rdynamic gcc (linker) flag for this to work
388
389 for (i = 0; i < size; i++) //skip useless functions
390 L<<Logger::Error<<strings[i]<<endl;
391
392
393 signal(SIGABRT, SIG_DFL);
394 abort();//hopefully will give core
395
396}
397#endif
398
399//! The main function of pdns, the pdns process
400int main(int argc, char **argv)
ba1a571d
CH
401{
402 versionSetProduct("Authoritative Server");
02116dff
BH
403 reportAllTypes(); // init MOADNSParser
404
12c86877
BH
405 s_programname="pdns";
406 s_starttime=time(0);
407
408#ifdef __linux__
409 signal(SIGSEGV,tbhandler);
410 signal(SIGFPE,tbhandler);
411 signal(SIGABRT,tbhandler);
412 signal(SIGILL,tbhandler);
413#endif
414
35b9a6ff
PD
415#if __GNUC__ >= 3
416 std::ios_base::sync_with_stdio(false);
417#endif
12c86877
BH
418
419 L.toConsole(Logger::Warning);
420 try {
421 declareArguments();
422 UNIX_declareArguments();
c4db07b7 423
e8d78143 424 ::arg().laxParse(argc,argv); // do a lax parse
12c86877 425
c4db07b7 426 if(::arg().mustDo("version")) {
ba1a571d 427 showProductVersion();
c4db07b7
PD
428 exit(99);
429 }
430
e8d78143
BH
431 if(::arg()["config-name"]!="")
432 s_programname+="-"+::arg()["config-name"];
12c86877
BH
433
434 (void)theL(s_programname);
435
e8d78143 436 string configname=::arg()["config-dir"]+"/"+s_programname+".conf";
12c86877
BH
437 cleanSlashes(configname);
438
e8d78143
BH
439 if(!::arg().mustDo("config") && !::arg().mustDo("no-config")) // "config" == print a configuration file
440 ::arg().laxFile(configname.c_str());
12c86877 441
e8d78143
BH
442 ::arg().laxParse(argc,argv); // reparse so the commandline still wins
443 if(!::arg()["logging-facility"].empty()) {
f8499e52
BH
444 int val=logFacilityToLOG(::arg().asNum("logging-facility") );
445 if(val >= 0)
446 theL().setFacility(val);
6e2514e4 447 else
4957a608 448 L<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
12c86877
BH
449 }
450
e8d78143
BH
451 L.setLoglevel((Logger::Urgency)(::arg().asNum("loglevel")));
452 L.toConsole((Logger::Urgency)(::arg().asNum("loglevel")));
12c86877 453
e8d78143
BH
454 if(::arg().mustDo("help") || ::arg().mustDo("config")) {
455 ::arg().set("daemon")="no";
456 ::arg().set("guardian")="no";
12c86877
BH
457 }
458
e8d78143
BH
459 if(::arg().mustDo("guardian") && !isGuarded(argv)) {
460 if(::arg().mustDo("daemon")) {
4957a608
BH
461 L.toConsole(Logger::Critical);
462 daemonize();
12c86877
BH
463 }
464 guardian(argc, argv);
465 // never get here, guardian will reinvoke process
466 cerr<<"Um, we did get here!"<<endl;
467 }
45fdd612 468
12c86877
BH
469
470 // we really need to do work - either standalone or as an instance
5488e86b
PD
471
472#ifdef __linux__
473 if(!::arg().mustDo("traceback-handler")) {
474 L<<Logger::Warning<<"Disabling traceback handler"<<endl;
475 signal(SIGSEGV,SIG_DFL);
476 signal(SIGFPE,SIG_DFL);
477 signal(SIGABRT,SIG_DFL);
478 signal(SIGILL,SIG_DFL);
479 }
480#endif
481
a28a204a
BH
482 seedRandom(::arg()["entropy-source"]);
483
12c86877 484 loadModules();
e8d78143 485 BackendMakers().launch(::arg()["launch"]); // vrooooom!
f4137d84 486
e8d78143 487 if(!::arg().getCommands().empty()) {
49daa3cd
BH
488 cerr<<"Fatal: non-option on the command line, perhaps a '--setting=123' statement missed the '='?"<<endl;
489 exit(99);
490 }
f4137d84 491
e8d78143 492 if(::arg().mustDo("help")) {
12c86877 493 cerr<<"syntax:"<<endl<<endl;
e8d78143 494 cerr<<::arg().helpstring(::arg()["help"])<<endl;
12c86877
BH
495 exit(99);
496 }
497
e8d78143
BH
498 if(::arg().mustDo("config")) {
499 cout<<::arg().configstring()<<endl;
12c86877
BH
500 exit(99);
501 }
502
e8d78143 503 if(::arg().mustDo("list-modules")) {
12c86877
BH
504 vector<string>modules=BackendMakers().getModules();
505 cerr<<"Modules available:"<<endl;
506 for(vector<string>::const_iterator i=modules.begin();i!=modules.end();++i)
4957a608 507 cout<<*i<<endl;
12c86877
BH
508
509 exit(99);
510 }
da44c9ea 511
203c0755
BH
512 if(::arg().mustDo("fancy-records")) {
513 reportFancyTypes();
514 }
515
e8d78143 516 if(!::arg().asNum("local-port")) {
da44c9ea
BH
517 L<<Logger::Error<<"Unable to launch, binding to no port or port 0 makes no sense"<<endl;
518 exit(99); // this isn't going to fix itself either
519 }
12c86877
BH
520 if(!BackendMakers().numLauncheable()) {
521 L<<Logger::Error<<"Unable to launch, no backends configured for querying"<<endl;
da44c9ea 522 exit(99); // this isn't going to fix itself either
12c86877 523 }
e8d78143 524 if(::arg().mustDo("daemon")) {
12c86877
BH
525 L.toConsole(Logger::None);
526 if(!isGuarded(argv))
4957a608 527 daemonize();
12c86877
BH
528 }
529
530 if(isGuarded(argv)) {
531 L<<Logger::Warning<<"This is a guarded instance of pdns"<<endl;
532 dl=new DynListener; // listens on stdin
533 }
534 else {
535 L<<Logger::Warning<<"This is a standalone pdns"<<endl;
536
e8d78143 537 if(::arg().mustDo("control-console"))
4957a608 538 dl=new DynListener();
12c86877 539 else
4957a608 540 dl=new DynListener(s_programname);
12c86877
BH
541
542 writePid();
543 }
3c90953e
PD
544 DynListener::registerFunc("SHOW",&DLShowHandler, "show a specific statistic or * to get a list", "<statistic>");
545 DynListener::registerFunc("RPING",&DLPingHandler, "ping instance");
546 DynListener::registerFunc("QUIT",&DLRQuitHandler, "quit daemon");
547 DynListener::registerFunc("UPTIME",&DLUptimeHandler, "get instance uptime");
548 DynListener::registerFunc("NOTIFY-HOST",&DLNotifyHostHandler, "notify host for specific domain", "<domain> <host>");
549 DynListener::registerFunc("NOTIFY",&DLNotifyHandler, "queue a notification", "<domain>");
550 DynListener::registerFunc("RELOAD",&DLReloadHandler, "reload all zones");
551 DynListener::registerFunc("REDISCOVER",&DLRediscoverHandler, "discover any new zones");
552 DynListener::registerFunc("VERSION",&DLVersionHandler, "get instance version");
553 DynListener::registerFunc("PURGE",&DLPurgeHandler, "purge entries from packet cache", "[<record>]");
554 DynListener::registerFunc("CCOUNTS",&DLCCHandler, "get cache statistics");
ba7244a5 555 DynListener::registerFunc("QTYPES", &DLQTypesHandler, "get QType statistics");
93698ef3
PD
556 DynListener::registerFunc("RESPSIZES", &DLRSizesHandler, "get histogram of response sizes");
557 DynListener::registerFunc("REMOTES", &DLRemotesHandler, "get top remotes");
3c90953e
PD
558 DynListener::registerFunc("SET",&DLSettingsHandler, "set config variables", "<var> <value>");
559 DynListener::registerFunc("RETRIEVE",&DLNotifyRetrieveHandler, "retrieve slave domain", "<domain>");
64bcb6be 560 DynListener::registerFunc("CURRENT-CONFIG",&DLCurrentConfigHandler, "Retrieve the current configuration");
040712e0
BH
561
562 if(!::arg()["tcp-control-address"].empty()) {
563 DynListener* dlTCP=new DynListener(ComboAddress(::arg()["tcp-control-address"], ::arg().asNum("tcp-control-port")));
564 dlTCP->go();
565 }
12c86877 566
12c86877 567 // reparse, with error checking
e8d78143
BH
568 if(!::arg().mustDo("no-config"))
569 ::arg().file(configname.c_str());
570 ::arg().parse(argc,argv);
5bc3abe7
PD
571
572 if(::arg()["server-id"].empty()) {
573 char tmp[128];
574 gethostname(tmp, sizeof(tmp)-1);
575 ::arg().set("server-id")=tmp;
576 }
577
12c86877
BH
578 UeberBackend::go();
579 N=new UDPNameserver; // this fails when we are not root, throws exception
580
e8d78143 581 if(!::arg().mustDo("disable-tcp"))
12c86877
BH
582 TN=new TCPNameserver;
583 }
584 catch(const ArgException &A) {
585 L<<Logger::Error<<"Fatal error: "<<A.reason<<endl;
586 exit(1);
587 }
588
589 declareStats();
590 DLOG(L<<Logger::Warning<<"Verbose logging in effect"<<endl);
12c86877 591
ba1a571d 592 showProductVersion();
12c86877
BH
593
594 try {
12c86877
BH
595 mainthread();
596 }
3f81d239 597 catch(PDNSException &AE) {
e8d78143 598 if(!::arg().mustDo("daemon"))
12c86877
BH
599 cerr<<"Exiting because: "<<AE.reason<<endl;
600 L<<Logger::Error<<"Exiting because: "<<AE.reason<<endl;
601 }
adc10f99 602 catch(std::exception &e) {
e8d78143 603 if(!::arg().mustDo("daemon"))
12c86877
BH
604 cerr<<"Exiting because of STL error: "<<e.what()<<endl;
605 L<<Logger::Error<<"Exiting because of STL error: "<<e.what()<<endl;
606 }
607 catch(...) {
608 cerr<<"Uncaught exception of unknown type - sorry"<<endl;
609 }
610
611 exit(1);
612
613}
614
615