I think this is the problem: When a child is reaped normally after
exiting due to MaxSpareServers or MaxRequestsPerChild, it remains in
the scoreboard with status set to SERVER_DEAD, and it is removed from
the pid table.

Often that slot will be reused by a child created subsequently.

If it is never reused before termination or hard restart,
reclaim_child_processes() will see it in this code and complain that
it isn't in the pid table:

        for (i = 0; i < max_daemons_limit; ++i) {
            int pid = ap_scoreboard_image->parent[i].pid;

            if (pid == my_pid || pid == 0)
                continue;

            if (!in_pid_table(pid)) {
                ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
                             "Bad pid (%d) in scoreboard slot %d", pid, i);
                continue;
            }

But it doesn't need to complain if the child is in the scoreboard with
state SERVER_DEAD, since that means it exited previously and is out of
the pid table.

Here's a hack to look out for that situation:

             if (!in_pid_table(pid)) {
-                ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
-                             "Bad pid (%d) in scoreboard slot %d", pid, i);
+                 /* Report an error if the scoreboard state for this child is
+                  * something besides SERVER_DEAD or if we can't find the
+                  * child slot.
+                  *
+                  * It is okay to find it with state SERVER_DEAD.  The child
+                  * exited normally, the state was set to SERVER_DEAD, and we
+                  * didn't subsequently reuse that scoreboard slot for another
+                  * child.
+                  */
+                int child_slot = find_child_by_pid(pid);
+
+                if (child_slot < 0
+                    ||
ap_scoreboard_image->servers[child_slot].status != SERVER_DEAD) {
+                    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
server_conf,
+                                 "Bad pid (%d) in scoreboard slot %d", pid, i);
+                }
+                else {
+                    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
server_conf,
+                                 "avoided bad pid msg for %d;
child_slot %d, status %d",
+                                 pid, child_slot, child_slot >= 0 ?
ap_scoreboard_image->servers[child_slot].status : -1);
+                }
                 continue;
             }

The "avoided bad pid" msg is just for debugging, of course.

This is perhaps not cool on whatever imaginary machines keep the
scoreboard in a file.  I never fully grokked the sync-scoreboard-image
requirements.

Reply via email to