request->component, request->module);
} else {
request->delay = USEC * request->root->max_request_time;
- RDEBUG2("WARNING: Child is still stuck");
+ RDEBUG2("WARNING: Child is hung after \"max_request_time\" for request %u",
+ request->number);
}
tv_add(&request->when, request->delay);
}
#endif
- if (home->state == HOME_STATE_IS_DEAD) {
- rad_assert(home->ev != NULL); /* or it will never wake up */
+ /*
+ * If it's not alive, don't try to make it a zombie.
+ */
+ if (home->state != HOME_STATE_ALIVE) {
+ /*
+ * Don't check home->ev due to race conditions.
+ */
return;
}
/*
- * Enable the zombie period when we notice that the home
- * server hasn't responded. We do NOT back-date the start
- * of the zombie period.
+ * We've received a real packet recently. Don't mark the
+ * server as zombie until we've received NO packets for a
+ * while. The "1/4" of zombie period was chosen rather
+ * arbitrarily. It's a balance between too short, which
+ * gives quick fail-over and fail-back, or too long,
+ * where the proxy still sends packets to an unresponsive
+ * home server.
*/
- if (home->state == HOME_STATE_ALIVE) {
- home->state = HOME_STATE_ZOMBIE;
- home->zombie_period_start = now;
- fr_event_delete(el, &home->ev);
- home->currently_outstanding = 0;
- home->num_received_pings = 0;
-
- radlog(L_PROXY, "Marking home server %s port %d as zombie (it looks like it is dead).",
- inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
- buffer, sizeof(buffer)),
- home->port);
-
- /*
- * Start pinging the home server.
- */
- ping_home_server(home);
+ if ((home->last_packet + ((home->zombie_period + 3) / 4)) >= now.tv_sec) {
+ return;
}
+
+ /*
+ * Enable the zombie period when we notice that the home
+ * server hasn't responded for a while. We back-date the
+ * zombie period to when we last received a response from
+ * the home server.
+ */
+ home->state = HOME_STATE_ZOMBIE;
+
+ home->zombie_period_start.tv_sec = home->last_packet;
+ home->zombie_period_start.tv_sec = USEC / 2;
+
+ fr_event_delete(el, &home->ev);
+ home->currently_outstanding = 0;
+ home->num_received_pings = 0;
+
+ radlog(L_PROXY, "Marking home server %s port %d as zombie (it looks like it is dead).",
+ inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
+ buffer, sizeof(buffer)),
+ home->port);
+
+ /*
+ * Start pinging the home server.
+ */
+ ping_home_server(home);
}
#endif
case REQUEST_RUNNING:
/*
* If we're not thread-capable, OR we're capable,
- * but have been told to run without threads,
- * complain when the requests is queued for a
- * thread, or running in a child thread.
+ * but have been told to run without threads, and
+ * the request is still running. This is usually
+ * because the request was proxied, and the home
+ * server didn't respond.
*/
#ifdef HAVE_PTHREAD_H
if (!have_children)
#endif
{
- rad_assert("We do not have threads, but the request is marked as queued or running in a child thread" == NULL);
- break;
+ goto done;
}
#ifdef HAVE_PTHREAD_H
*/
if (have_children &&
(pthread_equal(request->child_pid, NO_SUCH_CHILD_PID) == 0)) {
- radlog(L_ERR, "WARNING: Unresponsive child in module %s component %s",
- request->module ? request->module : "<server core>",
- request->component ? request->component : "<server core>");
+ radlog(L_ERR, "WARNING: Unresponsive child for request %u, in component %s module %s",
+ request->number,
+ request->component ? request->component : "<server core>",
+ request->module ? request->module : "<server core>");
+
}
request->delay = USEC;
* and clean it up.
*/
case REQUEST_DONE:
+ done:
#ifdef HAVE_PTHREAD_H
request->child_pid = NO_SUCH_CHILD_PID;
#endif
#ifdef WITH_PROXY
if (request->proxy) {
return process_proxy_reply(request);
-#endif
}
+#endif
return 1;
}
* and it should re-send it.
* If configured, encode, sign, and send.
*/
- if ((request->reply->code != 0) ||
- (request->listener->type == RAD_LISTEN_DETAIL)) {
+ if ((request->reply->code != 0)
+#ifdef WITH_DETAIL
+ || (request->listener->type == RAD_LISTEN_DETAIL)
+#endif
+ ) {
DEBUG_PACKET(request, request->reply, 1);
request->listener->send(request->listener, request);
}
}
+#ifdef WITH_PROXY
static void rad_retransmit_packet(REQUEST *request)
{
char buffer[256];
return 1;
}
-
+#endif
static void received_retransmit(REQUEST *request, const RADCLIENT *client)
{
/*
* We may want to quench the new request.
*/
- if ((listener->type != RAD_LISTEN_DETAIL) &&
+ if (
+#ifdef WITH_DETAIL
+ (listener->type != RAD_LISTEN_DETAIL) &&
+#endif
!can_handle_new_request(packet, client, root)) {
return 0;
}
* receive a packet? Setting this here means that we
* mark it alive on *any* packet, even if it's lost all
* of the *other* packets in the last 10s.
+ *
+ * This behavior could be configurable.
*/
request->home_server->state = HOME_STATE_ALIVE;
+ request->home_server->last_packet = now.tv_sec;
#ifdef WITH_COA
/*
}
#ifdef WITH_PROXY
else {
- int count = this->count;
+ int count;
/*
* Duplicate code
*/
if (this->status == RAD_LISTEN_STATUS_CLOSED) {
int count = this->count;
+
+#ifdef WITH_DETAIL
rad_assert(this->type != RAD_LISTEN_DETAIL);
+#endif
#ifdef WITH_PROXY
/*
xel = xel;
- if ((listener->type != RAD_LISTEN_DETAIL) &&
+ if (
+#ifdef WITH_DETAIL
+ (listener->type != RAD_LISTEN_DETAIL) &&
+#endif
(listener->fd < 0)) {
char buffer[256];
thread_pool_addrequest(request, fun);
}
-
+#ifdef WITH_DETAIL
/*
* This function is called periodically to see if this detail
* file is available for reading.
exit(1);
}
}
-
+#endif
static void event_status(struct timeval *wake)
{