]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/communicator.cc
auth: Wrap pthread_ objects
[thirdparty/pdns.git] / pdns / communicator.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <set>
27 #include <thread>
28 #include <boost/utility.hpp>
29
30 #include "packetcache.hh"
31 #include "utility.hh"
32 #include "communicator.hh"
33 #include "dnsbackend.hh"
34 #include "ueberbackend.hh"
35 #include "packethandler.hh"
36 #include "resolver.hh"
37 #include "logger.hh"
38 #include "dns.hh"
39 #include "arguments.hh"
40 #include "packetcache.hh"
41 #include "threadname.hh"
42
43 // there can be MANY OF THESE
44 void CommunicatorClass::retrievalLoopThread(void)
45 {
46 setThreadName("pdns/comm-retre");
47 for(;;) {
48 d_suck_sem.wait();
49 SuckRequest sr;
50 {
51 std::lock_guard<std::mutex> l(d_lock);
52 if(d_suckdomains.empty())
53 continue;
54
55 sr=d_suckdomains.front();
56 d_suckdomains.pop_front();
57 }
58 suck(sr.domain, sr.master);
59 }
60 }
61
62 void CommunicatorClass::loadArgsIntoSet(const char *listname, set<string> &listset)
63 {
64 vector<string> parts;
65 stringtok(parts, ::arg()[listname], ", \t");
66 for (vector<string>::const_iterator iter = parts.begin(); iter != parts.end(); ++iter) {
67 try {
68 ComboAddress caIp(*iter, 53);
69 listset.insert(caIp.toStringWithPort());
70 }
71 catch(PDNSException &e) {
72 g_log<<Logger::Error<<"Unparseable IP in "<<listname<<". Error: "<<e.reason<<endl;
73 _exit(1);
74 }
75 }
76 }
77
78 void CommunicatorClass::go()
79 {
80 try {
81 PacketHandler::s_allowNotifyFrom.toMasks(::arg()["allow-notify-from"] );
82 }
83 catch(PDNSException &e) {
84 g_log<<Logger::Error<<"Unparseable IP in allow-notify-from. Error: "<<e.reason<<endl;
85 _exit(1);
86 }
87
88 std::thread mainT(std::bind(&CommunicatorClass::mainloop, this));
89 mainT.detach();
90
91 for(int n=0; n < ::arg().asNum("retrieval-threads", 1); ++n) {
92 std::thread retrieve(std::bind(&CommunicatorClass::retrievalLoopThread, this));
93 retrieve.detach();
94 }
95
96 d_preventSelfNotification = ::arg().mustDo("prevent-self-notification");
97
98 try {
99 d_onlyNotify.toMasks(::arg()["only-notify"]);
100 }
101 catch(PDNSException &e) {
102 g_log<<Logger::Error<<"Unparseable IP in only-notify. Error: "<<e.reason<<endl;
103 _exit(1);
104 }
105
106 loadArgsIntoSet("also-notify", d_alsoNotify);
107
108 loadArgsIntoSet("forward-notify", PacketHandler::s_forwardNotify);
109 }
110
111 void CommunicatorClass::mainloop(void)
112 {
113 try {
114 setThreadName("pdns/comm-main");
115 signal(SIGPIPE,SIG_IGN);
116 g_log<<Logger::Error<<"Master/slave communicator launching"<<endl;
117 PacketHandler P;
118 d_tickinterval=::arg().asNum("slave-cycle-interval");
119 makeNotifySockets();
120
121 int rc;
122 time_t next, tick;
123
124 for(;;) {
125 slaveRefresh(&P);
126 masterUpdateCheck(&P);
127 tick=doNotifications(&P); // this processes any notification acknowledgements and actually send out our own notifications
128
129 tick = min (tick, d_tickinterval);
130
131 next=time(0)+tick;
132
133 while(time(0) < next) {
134 rc=d_any_sem.tryWait();
135
136 if(rc) {
137 bool extraSlaveRefresh = false;
138 Utility::sleep(1);
139 {
140 std::lock_guard<std::mutex> l(d_lock);
141 if (d_tocheck.size())
142 extraSlaveRefresh = true;
143 }
144 if (extraSlaveRefresh)
145 slaveRefresh(&P);
146 }
147 else {
148 // eat up extra posts to avoid busy looping if many posts were done
149 while (d_any_sem.tryWait() == 0) {
150 }
151 break; // something happened
152 }
153 // this gets executed at least once every second
154 doNotifications(&P);
155 }
156 }
157 }
158 catch(PDNSException &ae) {
159 g_log<<Logger::Error<<"Exiting because communicator thread died with error: "<<ae.reason<<endl;
160 Utility::sleep(1);
161 _exit(1);
162 }
163 catch(std::exception &e) {
164 g_log<<Logger::Error<<"Exiting because communicator thread died with STL error: "<<e.what()<<endl;
165 _exit(1);
166 }
167 catch( ... )
168 {
169 g_log << Logger::Error << "Exiting because communicator caught unknown exception." << endl;
170 _exit(1);
171 }
172 }
173