Re: Crash after server move

Ammaross Danan <[email protected]> Thu, 29 Mar 2007 14:00:13 -0600
Newsgroups gmane.games.devel.mud.rom
Organization Ardenmore
Message-ID <[email protected]>
Valnir wrote:

Program terminated with signal 11, Segmentation fault.
#0  0x080b373c in set_host (ch=0xb74f63bc, d=0xb74f5240) at comm.c:5793
5793                free_string(ch->usrdata->alt_hosts[h]);
(gdb) print ch->usrdata
$1 = (USER_DATA *) 0xb74f60b0
(gdb) print h
$2 = -1219534064
(gdb) print ch->usrdata->alt_hosts[h]
Cannot access memory at address 0x948ced3c
(gdb) 


Well, we found your symptom, now what is the problem? You ask how can h become -1219534064 inside a for loop. I've seen it happen a couple of ways. First, the int gets incremented to the point it flips negative, or it gets assigned the value of a pointer, such as h = (int) ch;


> #0  0x080b373c in set_host (ch=0xb74f63bc, d=0xb74f5240) at comm.c:5793
> 5793                free_string(ch->usrdata->alt_hosts[h]);
> (gdb) print i
> $1 = 6
> (gdb)
>
> merc.h:    char *               alt_hosts[MAX_HOSTS];   /* last X hosts */
>
> /* the entire function */
> void set_host ( CHAR_DATA *ch, DESCRIPTOR_DATA *d )
> {
>     char *hosts[MAX_HOSTS];
>     int h, i = 0;
>
>     if ( ch == NULL || d == NULL )
>     {
>         bug( "Set_host: ch or d is NULL!", 0 );
>         return;
>     }
>
>     if ( IS_NPC(ch) )
>     {
>         send_to_char( "Mobs don't have descriptors or hosts.\n\r", ch );
>         return;
>     }
>
>     free_string( ch->pcdata->host );
>     ch->pcdata->host = str_dup( d->host );
>     free_string( ch->usrdata->host );
>     ch->usrdata->host = str_dup( d->host );
>
>     /* is this host already our most recent? */
>     if ( !str_cmp( ch->usrdata->alt_hosts[0], d->host ) )
>         return;
>
>     /* set array elements to '\0' */
>     for ( h = 0; h < MAX_HOSTS; h++ )
>         hosts[h] = &str_empty[0];
>
>     hosts[i++] = str_dup(d->host);
>   
First, as an FYI, this line is going to cause an off-by-one error.
>     /* consolidate list and remove the current host from the list, if needed
> */
>     for ( h = 0; h < MAX_HOSTS; h++ )
>     {
>         if ( !str_cmp( ch->usrdata->alt_hosts[h], d->host ) )
>             continue;
>
>         if ( !IS_NULLSTR(ch->usrdata->alt_hosts[h]) )
>         {
>             hosts[i++] = str_dup(ch->usrdata->alt_hosts[h]);
>   
At the first run through, this statement will be something like hosts[1] 
= str_dump( alt_hosts[0] ), if there are alt_hosts. If you have a full 
list (MAX_HOSTS in side), hosts will have an overrun, since it will be 
trying to assign to hosts[MAX_HOSTS] which is invalid memory. (actually, 
if you look, the int h is created immediately after hosts[], so 
hosts[MAX_HOSTS], in ram, probably points to the same place &h would. 
Try it out in GDB. print &hosts[<value of MAX_HOSTS>] and print &h and 
copy the results in your reply. I haven't tried it myself, so I'm not 
100% on the outcome either. :P)
>             free_string(ch->usrdata->alt_hosts[h]);
>             ch->usrdata->alt_hosts[h] = &str_empty[0];
>         }
>     }
>
>     /* clear list and re-add entries */
>     for ( h = 0, i = 0; h < MAX_HOSTS; h++ )
>     {
>         if ( !IS_NULLSTR(hosts[i]) )
>             ch->usrdata->alt_hosts[h] = str_dup(hosts[i++]);
>         else
>             break;
>     }
>
>     save_account( ch->usrdata );
>     return;
> }
>
> Let me know if this helps you understand my problem.
>
> - Valnir
>
>
>
>
> From: David Wilson [mailto:[email protected]] 
> Sent: Wednesday, March 28, 2007 9:01 PM
> To: Nathan Kodak
> Cc: [email protected]
> Subject: Re: Crash after server move
>
> On 3/28/07, Valnir <[email protected]> wrote:
> Below is the output from the core and the info you requested. I'm curious
> how "h" could be such an odd ball number while inside a defined for loop?
>
> - Valnir
>
> What's the value of i? It looks like you have an overflow somewhere. What's
> the size of the alt_hosts array? 
>
> -David
>  
>
> Program terminated with signal 11, Segmentation fault.
> #0 0x080b373c in set_host (ch=0xb74f63bc, d=0xb74f5240) at comm.c:5793
> 5793 free_string(ch->usrdata->alt_hosts[h]);
> (gdb) print ch->usrdata
> $1 = (USER_DATA *) 0xb74f60b0
> (gdb) print h
> $2 = -1219534064
> (gdb) print ch->usrdata->alt_hosts[h]
> Cannot access memory at address 0x948ced3c 
> (gdb)
>
>
> ________________________________________
> From: [email protected] on behalf of Ammaross Danan
> Sent: Wed 3/28/2007 2:27 AM
> To: [email protected]
> Subject: Re: Crash after server move
> Valnir wrote:
>   
>> We're getting ready to port our mud to a new server and we're having a bit
>> of an issue. Everything compiles clean, but when we login we get past our 
>> account login and when we select what character to play the mud crashes.
>>
>> Program terminated with signal 11, Segmentation fault.
>> #0 0x080b373c in set_host (ch=0xb74f63bc, d=0xb74f5240) at comm.c :5793
>> 5793 free_string(ch->usrdata->alt_hosts[h]);
>>
>>     
> print ch->usrdata
> print h
> print ch->usrdata->alt_hosts[h]
>
> These will give us the proper feedback on exactly what is causing the 
> crash. I'm willing to bet ch->usrdata is 0x0, or is 0x3 or some such
> invalid mem address (caused by an overrun of some sort). If it is, you
> may want to insert an alloc_mem in the new_char_data() and the
> corresponding free_mem() in the free_char_data().
>   
>> (gdb) where
>> #0 0x080b373c in set_host (ch=0xb74f63bc, d=0xb74f5240) at comm.c:5793
>> #1 0x080a905c in nanny (d=0xb74f5240, argument=0xb74f5661 "Valnir") at 
>> comm.c:2560
>> #2 0x080a4a49 in game_loop_unix (control=4) at comm.c:885
>> #3 0x080a4424 in main (argc=2, argv=0xbf911974) at comm.c:490
>> (gdb)
>>
>> It's crashing while trying to update the listing of hosts that a players 
>>     
> has
>   
>> connected from.
>>
>> /* consolidate list and remove the current host from the list, if
>>     
> needed
>   
>> */
>>
>>     
> might want to put this block inside a if ( ch->usrdata != null ) check
>   
>> for ( h = 0; h < MAX_HOSTS; h++ )
>> {
>> if ( !str_cmp( ch->usrdata->alt_hosts[h], d->host ) )
>> continue;
>>
>> if ( !IS_NULLSTR(ch->usrdata->alt_hosts[h]) )
>> {
>> hosts[i++] = str_dup(ch->usrdata->alt_hosts[h]);
>> free_string(ch->usrdata->alt_hosts[h]);
>> ch->usrdata->alt_hosts[h] = &str_empty[0];
>> }
>> }
>> The new server is running GCC 4.1.1 and any help would be greatly
>> appreciated. Thanks!
>>
>> - Valnir
>>     
>
>
>
>   
Ammaross Danan
-- 
ROM mailing list
[email protected]
Unsubscribe here ->>> http://www.rom.org/cgi-bin/mailman/listinfo/rom