• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 18837422702

27 Oct 2025 10:15AM UTC coverage: 73.025% (+0.02%) from 73.004%
18837422702

Pull #16375

github

web-flow
Merge 2f23fc90d into 82ea647b4
Pull Request #16375: dnsdist: Include a Date: response header for rejected HTTP1 requests

38279 of 63122 branches covered (60.64%)

Branch coverage included in aggregate %.

0 of 11 new or added lines in 1 file covered. (0.0%)

10680 existing lines in 98 files now uncovered.

127481 of 163870 relevant lines covered (77.79%)

5384548.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.96
/pdns/epollmplexer.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
#include "mplexer.hh"
26
#include "sstuff.hh"
27
#include <iostream>
28
#include <unistd.h>
29
#include "misc.hh"
30
#ifdef __linux__
31
#include <sys/epoll.h>
32
#endif
33

34
#include "namespaces.hh"
35

36
class EpollFDMultiplexer : public FDMultiplexer
37
{
38
public:
39
  EpollFDMultiplexer(unsigned int maxEventsHint);
40
  ~EpollFDMultiplexer() override
41
  {
3,213✔
42
    if (d_epollfd >= 0) {
3,213✔
43
      close(d_epollfd);
3,211✔
44
    }
3,211✔
45
  }
3,213✔
46

47
  int run(struct timeval* tv, int timeout = 500) override;
48
  void getAvailableFDs(std::vector<int>& fds, int timeout) override;
49

50
  void addFD(int fd, FDMultiplexer::EventKind kind) override;
51
  void removeFD(int fd, FDMultiplexer::EventKind kind) override;
52
  void alterFD(int fd, FDMultiplexer::EventKind from, FDMultiplexer::EventKind to) override;
53

54
  string getName() const override
55
  {
185✔
56
    return "epoll";
185✔
57
  }
185✔
58

59
private:
60
  int d_epollfd;
61
  std::vector<epoll_event> d_eevents;
62
};
63

64
static FDMultiplexer* makeEpoll(unsigned int maxEventsHint)
65
{
7,402✔
66
  return new EpollFDMultiplexer(maxEventsHint);
7,402✔
67
}
7,402✔
68

69
static struct EpollRegisterOurselves
70
{
71
  EpollRegisterOurselves()
72
  {
993✔
73
    FDMultiplexer::getMultiplexerMap().emplace(0, &makeEpoll); // priority 0!
993✔
74
  }
993✔
75
} doItEpoll;
76

77
EpollFDMultiplexer::EpollFDMultiplexer(unsigned int maxEventsHint) :
78
  d_eevents(maxEventsHint)
6,430✔
79
{
7,400✔
80
  d_epollfd = epoll_create(static_cast<int>(maxEventsHint)); // not hard max, just a hint that is actually ignored since Linux 2.6.8
7,400✔
81
  if (d_epollfd < 0) {
7,400✔
UNCOV
82
    throw FDMultiplexerException("Setting up epoll: " + stringerror());
6✔
UNCOV
83
  }
6✔
84
  int fd = socket(AF_INET, SOCK_DGRAM, 0); // for self-test
7,394✔
85

86
  if (fd < 0) {
7,394!
87
    return;
×
88
  }
×
89

90
  try {
7,394✔
91
    addReadFD(fd, 0);
7,394✔
92
    removeReadFD(fd);
7,394✔
93
    close(fd);
7,394✔
94
    return;
7,394✔
95
  }
7,394✔
96
  catch (const FDMultiplexerException& fe) {
7,394✔
97
    close(fd);
×
98
    close(d_epollfd);
×
99
    throw FDMultiplexerException("epoll multiplexer failed self-test: " + string(fe.what()));
×
100
  }
×
101
}
7,394✔
102

103
static uint32_t convertEventKind(FDMultiplexer::EventKind kind)
104
{
51,312✔
105
  switch (kind) {
51,312✔
106
  case FDMultiplexer::EventKind::Read:
49,406✔
107
    return EPOLLIN;
49,406✔
108
  case FDMultiplexer::EventKind::Write:
1,903✔
109
    return EPOLLOUT;
1,903✔
110
  case FDMultiplexer::EventKind::Both:
4✔
111
    return EPOLLIN | EPOLLOUT;
4✔
112
  }
51,312✔
113

114
  throw std::runtime_error("Unhandled event kind in the epoll multiplexer");
×
115
}
51,312✔
116

117
void EpollFDMultiplexer::addFD(int fd, FDMultiplexer::EventKind kind)
118
{
49,382✔
119
  struct epoll_event eevent;
49,382✔
120

121
  eevent.events = convertEventKind(kind);
49,382✔
122

123
  eevent.data.u64 = 0; // placate valgrind (I love it so much)
49,382✔
124
  eevent.data.fd = fd;
49,382✔
125

126
  if (epoll_ctl(d_epollfd, EPOLL_CTL_ADD, fd, &eevent) < 0) {
49,382✔
127
    throw FDMultiplexerException("Adding fd to epoll set: " + stringerror());
4✔
128
  }
4✔
129
}
49,382✔
130

131
void EpollFDMultiplexer::removeFD(int fd, FDMultiplexer::EventKind)
132
{
34,726✔
133
  struct epoll_event dummy;
34,726✔
134
  dummy.events = 0;
34,726✔
135
  dummy.data.u64 = 0;
34,726✔
136

137
  if (epoll_ctl(d_epollfd, EPOLL_CTL_DEL, fd, &dummy) < 0) {
34,726!
138
    throw FDMultiplexerException("Removing fd from epoll set: " + stringerror());
×
139
  }
×
140
}
34,726✔
141

142
void EpollFDMultiplexer::alterFD(int fd, FDMultiplexer::EventKind, FDMultiplexer::EventKind to)
143
{
1,960✔
144
  struct epoll_event eevent;
1,960✔
145
  eevent.events = convertEventKind(to);
1,960✔
146
  eevent.data.u64 = 0; // placate valgrind (I love it so much)
1,960✔
147
  eevent.data.fd = fd;
1,960✔
148

149
  if (epoll_ctl(d_epollfd, EPOLL_CTL_MOD, fd, &eevent) < 0) {
1,960!
150
    throw FDMultiplexerException("Altering fd in epoll set: " + stringerror());
×
151
  }
×
152
}
1,960✔
153

154
void EpollFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
155
{
2,137✔
156
  int ret = epoll_wait(d_epollfd, d_eevents.data(), d_eevents.size(), timeout);
2,137✔
157

158
  if (ret < 0 && errno != EINTR) {
2,137!
159
    throw FDMultiplexerException("epoll returned error: " + stringerror());
×
160
  }
×
161

162
  for (int n = 0; n < ret; ++n) {
3,889✔
163
    fds.push_back(d_eevents[n].data.fd);
1,752✔
164
  }
1,752✔
165
}
2,137✔
166

167
int EpollFDMultiplexer::run(struct timeval* now, int timeout)
168
{
71,458✔
169
  InRun guard(d_inrun);
71,458✔
170

171
  int ret = epoll_wait(d_epollfd, d_eevents.data(), d_eevents.size(), timeout);
71,458✔
172
  gettimeofday(now, nullptr); // MANDATORY
71,458✔
173

174
  if (ret < 0 && errno != EINTR) {
71,458!
175
    throw FDMultiplexerException("epoll returned error: " + stringerror());
×
176
  }
×
177

178
  if (ret < 1) { // thanks AB!
71,458✔
179
    return 0;
34,964✔
180
  }
34,964✔
181

182
  int count = 0;
36,494✔
183

184
  for (int n = 0; n < ret; ++n) {
74,136✔
185
    if ((d_eevents[n].events & EPOLLIN) || (d_eevents[n].events & EPOLLERR) || (d_eevents[n].events & EPOLLHUP)) {
37,647!
186
      const auto& iter = d_readCallbacks.find(d_eevents[n].data.fd);
37,605✔
187
      if (iter != d_readCallbacks.end()) {
37,611✔
188
        iter->d_callback(iter->d_fd, iter->d_parameter);
37,606✔
189
        count++;
37,606✔
190
      }
37,606✔
191
    }
37,605✔
192

193
    if ((d_eevents[n].events & EPOLLOUT) || (d_eevents[n].events & EPOLLERR) || (d_eevents[n].events & EPOLLHUP)) {
37,659✔
194
      const auto& iter = d_writeCallbacks.find(d_eevents[n].data.fd);
428✔
195
      if (iter != d_writeCallbacks.end()) {
428✔
196
        iter->d_callback(iter->d_fd, iter->d_parameter);
33✔
197
        count++;
33✔
198
      }
33✔
199
    }
428✔
200
  }
37,642✔
201

202
  return count;
36,494✔
203
}
71,458✔
204

205
#if 0
206
void acceptData(int fd, funcparam_t& parameter)
207
{
208
  cout<<"Have data on fd "<<fd<<endl;
209
  Socket* sock=funcparam_t_cast<Socket*>(parameter);
210
  string packet;
211
  IPEndpoint rem;
212
  sock->recvFrom(packet, rem);
213
  cout<<"Received "<<packet.size()<<" bytes!\n";
214
}
215

216

217
int main()
218
{
219
  Socket s(AF_INET, SOCK_DGRAM);
220

221
  IPEndpoint loc("0.0.0.0", 2000);
222
  s.bind(loc);
223

224
  EpollFDMultiplexer sfm;
225

226
  sfm.addReadFD(s.getHandle(), &acceptData, &s);
227

228
  for(int n=0; n < 100 ; ++n) {
229
    sfm.run();
230
  }
231
  sfm.removeReadFD(s.getHandle());
232
  sfm.removeReadFD(s.getHandle());
233
}
234
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc