<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40579 >

> [EMAIL PROTECTED] - Mon Nov 24 23:50:05 2008]:
> 
> 2008/11/24 Madeline Book:
> >
> > Do you know what you did to get the segfault?
> 
>  That core is from public server.
> 
>  From logs it seems that sequence has been:
> 
>  /set aifill 0
>  ... which seemed to remove *all* the players (previous aifill was 5,
> and 5 players were removed)
>  Lost connection to xxx
>  ... and removal of one player is attempted again

I have confirmed that aifill 0 will sometimes remove all
players. :(

Strangely, just doing /set aifill 0 with one player does
not do anything (as expected), nor 1 or 2 then setting it
to zero. It is only when one does /set aifill 3 or more
and then does /set aifill 0 that all players including
non-aifill players are removed.

This causes both client and server to crash for 2.1.7;
trunk is not affected as far as I can see.

Investigating the code, it would look like that indeed
that call to aifill at the end of server_remove_player
is the problem, since server_remove_playe itself is
being called from aifill resulting in recursion.

So one fix would be to just undo my addition of that
call to aifill, but here is a patch that makes aifill
recursion-safe (at least for the remove case) and would
appear to fix the problem.

If no problems are found with the patch I would suggest
that server operators apply the patch to their public
servers, with my apologies [ahhh the gods of freeciv
are angry with meeeeeee].


----------------------------------------------------------------------
当たり前じゃ。
diff --git a/server/srv_main.c b/server/srv_main.c
index 981c7ba..b386a40 100644
--- a/server/srv_main.c
+++ b/server/srv_main.c
@@ -1593,14 +1593,22 @@ void aifill(int amount)
     send_player_info(pplayer, NULL);
   }
 
-  remove = game.info.nplayers - 1;
-  while (game.info.nplayers > amount && remove >= 0) {
-    struct player *pplayer = player_by_number(remove);
-
-    if (!pplayer->is_connected && !pplayer->was_created) {
-      server_remove_player(pplayer);
+  while (game.info.nplayers > amount) {
+    struct player *pplayer_rem = NULL;
+    remove = game.info.nplayers - 1;
+    while (remove >= 0) {
+      struct player *pplayer = player_by_number(remove);
+      if (!pplayer->is_connected && !pplayer->was_created) {
+        pplayer_rem = pplayer;
+        break;
+      }
+      remove--;
+    }
+    if (pplayer_rem) {
+      server_remove_player(pplayer_rem);
+    } else {
+      break;
     }
-    remove--;
   }
 }
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to