Complete.Org: Mailing Lists: Archives: freeciv-dev: July 1999:
[Freeciv-Dev] Server hangs on an Alpha

[Freeciv-Dev] Server hangs on an Alpha

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] Server hangs on an Alpha
From: Matthew OConnor <matthew@xxxxxxxxxxxxxx>
Date: Wed, 28 Jul 1999 16:01:13 -0500

I searched the bug tracking system and the mailing list archives so I
apologize if this has come up before, but I don't believe it has.

The Setup:
  Running Alpha Linux Redhat 6.0 with glibc 2.1.1-7 and egcs 2.91.66.
  int is 32-bit, long is 64-bit, long long is 64-bit, pointers are 64-bit

The Software:
  Freeciv 1.8.0, FreeCiv 1.8.1 and FreeCiv CVS (Wed Jul 28 1999)

Compilation Flags:
  All code was compiled with "-O0 -ggdb" no optimization was used.

The Bug:

  When you set the "generator" option to any value other than 1 the
  server hangs.  (Note: this bug is present on an Alpha, Intel-like
  machines work just fine)

  These exact steps will cause the server to hang for me:

     set generator 2
     create ai
     -- server hangs

  Also "set generator 3" and "set generator 4" will cause the server
  to hang.

Why I think it hangs:

  Lines numbers are with respect to FreeCiv 1.8.1.

  In the fillisland() function at line 989 of mapgen.c there is the
  following code:

     while (i && failsafe--) {

  On an Intel-like machine the value of "i" is usually less than 100
  and failsafe is in the tens of thousands.  On the Alpha (using a 
  generator greater than 1) the value of "i" is in the tens of
  millions as is failsafe.  So in fact the server hangs b/c it is
  in this while loop for a *really* long time.

  The fact that failsafe is so big is because in fillisland() at
  line 983 of mapgen.c it is shown that failsafe is dependent on "i".

  In turn at line 978 of mapgen.c (in fillisland()) we see the following
     i = *bucket / capac;

  So "i" is dependent on bucket (which is an int* passed into
  fillisland()) and capac.  Stepping through this code in GDB we find
  that capac always has reasonable values, but *bucket is extremely
  high.  Thus "i" is extremely big because *bucket is extremely big.

  Now the function that is calling fillisland() is makeisland().
  Inside of makeisland() we see at lines 1141 to lines 1145 of
  mapgen.c that the variables riverbuck, mountbuck, desertbuck,
  forestbuck and swampbuck are set to random values.

  Now also notice that inside makeisland() we are calling
  fillisland() several different times.  Each time passing in the
  address of one of the *buck variables that I mentioned above.

  Well these *buck variables are what the "*bucket" variable inside of
  fillisland() really is.  So the fact that "*bucket" is so large is
  b/c these *buck variables are so large.

  Now on a Intel-like machine the *buck variables always seem to be
  less than 1000 and negative.  On the Alpha they are positive and in
  the tens of millions.

  It almost seems as though these variables are never getting
  set...well we notice that initialization of these variables in
  contingent on an if-statement in makeisland() at line 1126.  The line

     if (!islemass) {

  Well the 1st time makeisland() is called islemass is 0, so we enter
  in the then-block of the if-statement.  Now this is were the
  weirdness happens.  I reproduce the then-block of the above
  if-statement so I can refer to it easily:

  Line 1126  if (!islemass) {
  Line 1127                               /* setup initial static parameters */
  Line 1128    balance = 0;
  Line 1129    isleindex = 3; /* 0= none, 1= arctic, 2= antarctic */
  Line 1130
  Line 1131    checkmass= totalmass;
  Line 1132
  Line 1133    /* caveat: this should really be sent to all players */
  Line 1134    if(totalmass>3000)
  Line 1135      freelog(LOG_NORMAL,"high landmass - this may take a few 
  Line 1136
  Line 1137    i = map.riverlength + map.mountains
  Line 1138                + map.deserts + map.forestsize + map.swampsize;
  Line 1139    i = i <= 90 ? 100 : i * 11 / 10;
  Line 1140    tilefactor = totalmass / i;
  Line 1141    riverbuck = -myrand(totalmass);
  Line 1142    mountbuck = -myrand(totalmass);
  Line 1143    desertbuck = -myrand(totalmass);
  Line 1144    forestbuck = -myrand(totalmass);
  Line 1145    swampbuck = -myrand(totalmass);
  Line 1146    lastplaced = totalmass;
  Line 1147  } else {

  Now on the 1st call to makeisland() islemass is zero.  We go through
  lines 1127 to 1140 just fine.  Then at line 1141 we "magically" go
  back to the beginning of makeisland().  Now remember, I compiled
  with -O0.  There is no code optimization going on.

  I can't say for sure what is happening.  Anyway that is about as far
  as I got before I had to give up.  I did try replacing myrand() and
  mysrand() w/ direct calls to rand() and srand() thinking there might
  have been an issue w/ the PRNG code, but it didn't fix anything.

  So a quick summary of why the program hangs:

    The program hangs because it goes into several really long while()

    The loops are really long because "i" and "failsafe" in fillisland()
    are really big.

    Failsafe is big because "i" is big and "i" is big because bucket is big

    bucket is big because the *buck variables in makeisland() are big.

    The *buck variables are big because they are never initialized

    The variables are never initialized because of a magic code jump
    right whey they are about to be set.

    I don't know why the magic code jump happens, I compiled with -O0.

    Perhaps a egcs bug?

Anyway that is all the information I have.  If anybody can provide
some more input or lists of things to try then I would appreciate it.
If it is a bug in egcs then I am at a complete loss as to how to verify
it as such.  The only time I have ever seen "magic code jumps" is when I am
debugging optimized code.

Thanks for your time.

[Prev in Thread] Current Thread [Next in Thread]