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

 There was another call of init_available_nations() at wrong time. And
sometimes it was not called when it should have been called.
 Attached patch moves init_available_nations() call to where it really
belong. Always initialize nations when their structure is created.
Never initialize them after they have been assigned to players.
 In addition to moving that one call, added several sanity checks and comments.


 - ML

diff -Nurd -X.diff_ignore freeciv/common/player.c freeciv/common/player.c
--- freeciv/common/player.c	2007-08-04 18:38:32.000000000 +0300
+++ freeciv/common/player.c	2007-08-08 17:54:00.000000000 +0300
@@ -330,6 +330,9 @@
     }
     pplayer->nation = pnation;
     return TRUE;
+  } else {
+    /* Nation already assigned to this player */
+    assert(pnation->player == pplayer);
   }
   return FALSE;
 }
diff -Nurd -X.diff_ignore freeciv/server/ruleset.c freeciv/server/ruleset.c
--- freeciv/server/ruleset.c	2007-08-07 14:24:36.000000000 +0300
+++ freeciv/server/ruleset.c	2007-08-08 17:46:38.000000000 +0300
@@ -3494,6 +3494,10 @@
 static void reset_player_nations(void)
 {
   players_iterate(pplayer) {
+    /* We cannot use player_set_nation() here since this is
+     * called before nations are loaded. Player pointers
+     * from nations will be initialized to NULL when nations are
+     * loaded. */
     pplayer->nation = NO_NATION_SELECTED;
     pplayer->city_style = 0;
   } players_iterate_end;
@@ -3548,6 +3552,9 @@
   load_ruleset_effects(&effectfile);
   load_ruleset_game();
 
+  /* Init nations we just loaded. */
+  init_available_nations();
+
   sanity_check_ruleset_data();
 
   precalc_tech_data();
diff -Nurd -X.diff_ignore freeciv/server/srv_main.c freeciv/server/srv_main.c
--- freeciv/server/srv_main.c	2007-08-07 00:07:45.000000000 +0300
+++ freeciv/server/srv_main.c	2007-08-08 18:00:16.000000000 +0300
@@ -1347,7 +1347,29 @@
     }
   }
   nations_iterate(nation) {
-    nation->player = NULL;
+    /* Even though this function is called init_available_nations(),
+     * nation->player should never have value assigned to it
+     * (since it has beeen initialized in load_rulesets() ). */
+    if (nation->player != NULL) {
+
+      freelog(LOG_ERROR, "Player assigned to nation before "
+                         "init_available_nations()");
+
+      /* When we enter this execution branch, assert() will always
+       * fail. This one just provides more informative message than
+       * simple assert(FAIL); */
+      assert(nation->player == NULL);
+
+      /* Try to handle error situation as well as we can */
+      if (nation->player->nation == nation) {
+        /* At least assignment is consistent. Leave nation assigned,
+         * and make sure that nation is also marked available. */
+        nation->is_available = TRUE;
+      } else {
+        /* Not consistent. Just initialize the pointer and hope for the best */
+        nation->player = NULL;
+      }
+    }
   } nations_iterate_end;
   send_ruleset_nations(game.est_connections);
 }
@@ -1889,8 +1911,6 @@
 **************************************************************************/
 static void srv_loop(void)
 {
-  init_available_nations();
-
   freelog(LOG_NORMAL, _("Now accepting new client connections."));
   while(server_state == PRE_GAME_STATE) {
     sniff_packets(); /* Accepting commands. */
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to