resolvers_destroy() runs at deinit, on the last remaining thread, and
closes the UDP nameserver sockets, which were created by the thread
their resolvers section's task was pinned to. With per-thread-group FD
tables, when that thread belongs to another group, its group's FD
table died with its last thread and already closed the socket, and the
stored number is only meaningful in that table, closing it from here
would actually close whatever FD carries the same number in this
thread's own table. So in that case, leave the FD alone.
free(ns->id);
free((char *)ns->conf.file);
if (ns->dgram) {
- if (ns->dgram->conn.t.sock.fd != -1) {
+ /* with per-thread-group FD tables, the socket belongs
+ * to the group of the resolvers task's thread; if it
+ * is not ours, it was already closed by the kernel
+ * when the last thread of that group exited, and its
+ * number is not valid in this thread's tables.
+ */
+ if (ns->dgram->conn.t.sock.fd != -1 &&
+ (!(global.tune.options & GTUNE_NO_TG_FD_SHARING) ||
+ (resolvers->t &&
+ ha_thread_info[resolvers->t->tid].tgid == tgid))) {
fd_delete(ns->dgram->conn.t.sock.fd);
close(ns->dgram->conn.t.sock.fd);
}