RecThreadInfo::setThreadId(currentThreadId);
recursorThread();
- for (unsigned int thread = 0; thread < RecThreadInfo::numRecursorThreads(); thread++) {
- if (thread == 1) {
- continue;
- }
+ // Skip handler thread (it might be still handling the quite-nicely) and 1, which is actually the main thread in this case
+ // hanlder thread (0) will be handled in main().
+ for (unsigned int thread = 2; thread < RecThreadInfo::numRecursorThreads(); thread++) {
auto& tInfo = RecThreadInfo::info(thread);
tInfo.thread.join();
if (tInfo.exitCode != 0) {
info.start(currentThreadId, "web+stat", cpusMap, log);
for (auto& tInfo : RecThreadInfo::infos()) {
+ if (tInfo.getName() == "web+stat") { // XXX testing for isHandler() does not work as expected!
+ continue;
+ }
tInfo.thread.join();
if (tInfo.exitCode != 0) {
ret = tInfo.exitCode;
RecursorControlParser::func_t* command = nullptr;
auto answer = RecursorControlParser::getAnswer(clientfd, msg, &command);
- g_rcc.send(clientfd, answer);
+ if (command != doExitNicely) {
+ g_rcc.send(clientfd, answer);
+ }
command();
+ if (command == doExitNicely) {
+ g_rcc.send(clientfd, answer);
+ g_rcc.~RecursorControlChannel();
+ }
}
catch (const std::exception& e) {
SLOG(g_log << Logger::Error << "Error dealing with control socket request: " << e.what() << endl,
}
}
+DoneRunning doneRunning;
+
int main(int argc, char** argv)
{
g_argc = argc;
}
ret = serviceMain(startupLog);
+ {
+ std::lock_guard lock(doneRunning.mutex);
+ doneRunning.done = true;
+ doneRunning.condVar.notify_one();
+ }
+ RecThreadInfo::joinThread0();
}
catch (const PDNSException& ae) {
SLOG(g_log << Logger::Error << "Exception: " << ae.reason << endl,
extern uint16_t g_minUdpSourcePort;
extern uint16_t g_maxUdpSourcePort;
extern bool g_regressionTestMode;
+struct DoneRunning
+{
+ std::mutex mutex;
+ std::condition_variable condVar;
+ std::atomic<bool> done{false};
+};
+extern DoneRunning doneRunning;
// you can ask this class for a UDP socket to send a query from
// this socket is not yours, don't even think about deleting it
mt = theMT;
}
+ static void joinThread0()
+ {
+ info(0).thread.join();
+ }
+
private:
// FD corresponding to TCP sockets this thread is listening on.
// These FDs are also in deferredAdds when we have one socket per
_exit(0); // regression test check for exit 0
#endif
g_log << Logger::Error << "Exiting on user request" << endl;
- g_rcc.~RecursorControlChannel();
if (!g_pidfname.empty()) {
unlink(g_pidfname.c_str()); // we can at least try..
if (nicely) {
RecursorControlChannel::stop = true;
+ {
+ std::unique_lock lock(doneRunning.mutex);
+ doneRunning.condVar.wait(lock, [] { return doneRunning.done.load(); });
+ }
+ // g_rcc.~RecursorControlChannel() do not call, will be done by caller!
}
else {
+ g_rcc.~RecursorControlChannel();
#if defined(__SANITIZE_ADDRESS__) && defined(HAVE_LEAK_SANITIZER_INTERFACE)
clearLuaScript();
pdns::coverage::dumpCoverageData();