# endif
#endif
);
+ log_err("server_stats_obtain: no response from worker %d "
+ "(stats timeout); returning zero stats for this worker",
+ who->thread_num);
+ /* A later reply from the worker, would be sizeof stats reply,
+ * and the worker_handle_control_cmd routine discards if
+ * it is not a 4byte command, when that is received here. */
+ memset(s, 0, sizeof(*s));
+ return;
+ }
+ if(!tube_read_msg(worker->cmd, &reply, &len, 0)) {
+ log_err("server_stats_obtain: failed to read stats from worker "
+ "(tube read error); returning zero stats for this worker");
+ memset(s, 0, sizeof(*s));
+ return;
+ }
+ if(len != (uint32_t)sizeof(*s)) {
+ log_err("server_stats_obtain: wrong stats length %d (expected %d); "
+ "discarding", (int)len, (int)sizeof(*s));
+ free(reply);
+ memset(s, 0, sizeof(*s));
+ return;
}
- if(!tube_read_msg(worker->cmd, &reply, &len, 0))
- fatal_exit("failed to read stats over cmd channel");
- if(len != (uint32_t)sizeof(*s))
- fatal_exit("stats on cmd channel wrong length %d %d",
- (int)len, (int)sizeof(*s));
memcpy(s, reply, (size_t)len);
free(reply);
}
verbose(VERB_ALGO, "write stats replymsg");
if(!tube_write_msg(worker->daemon->workers[0]->cmd,
(uint8_t*)&s, sizeof(s), 0))
- fatal_exit("could not write stat values over cmd channel");
+ log_err("could not write stat values over cmd channel");
}
void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
- Fix that fast_reload does not terminate the server
on malloc failure for dnstap, or if gethostname fails.
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+ - Fix after malloc failure for stats, then it drains the pipe
+ so the internal messaging stays correct. Also it does
+ not exit the server if stats pipe communication fails.
+ Thanks to Qifan Zhang, Palo Alto Networks, for the report.
16 June 2026: Wouter
- Fix to disallow $INCLUDE for secondary zones. Start up
}
}
+/** Drain the pipe of bytes. */
+static void
+fd_drain(int fd, uint32_t len)
+{
+ uint8_t discard[256];
+ uint32_t remaining = len;
+ while(remaining > 0) {
+ ssize_t n = read(fd, discard,
+ remaining < sizeof(discard) ? remaining : sizeof(discard));
+ if(n <= 0) break;
+ remaining -= (uint32_t)n;
+ }
+}
+
int
tube_handle_listen(struct comm_point* c, void* arg, int error,
struct comm_reply* ATTR_UNUSED(reply_info))
tube->cmd_msg = (uint8_t*)calloc(1, tube->cmd_len);
if(!tube->cmd_msg) {
log_err("malloc failure");
+ /* Drain the remaining bytes, since they belong to this
+ * message. The next message starts after it. */
+ fd_drain(c->fd, tube->cmd_len);
tube->cmd_read = 0;
return 0;
}
*buf = (uint8_t*)malloc(*len);
if(!*buf) {
log_err("tube read out of memory");
+ /* Drain the remaining bytes, since they belong to this
+ * message. The next message starts after it. */
+ fd_drain(fd, *len);
(void)fd_set_nonblock(fd);
return 0;
}