Crashing On Shutdown

  • Papaya Pete
  • Topic Author
  • Offline
  • Elite Member
  • Elite Member
More
3 years 1 month ago #7734 by Papaya Pete
Crashing On Shutdown was created by Papaya Pete
This is a problem I've had for a while, but haven't really dealt with it seeing as it didn't really affect very much (except for the crafting snippet). I'm hoping that by taking a fresh look at it, perhaps the problem can be found.

So, I found that it is not the crafting snippet that is the problem; I removed it completely (I think?) and it still suffers the same crash. I looked over the gdb tutorial a little bit, and here are the results of doing a quick test.
Mar 19 23:01:50 :: Normal termination of game.
Mar 19 23:01:50 :: Clearing game world.
Mar 19 23:01:50 :: Clearing other memory.
Mar 19 23:01:50 :: WARNING: Attempting to merge iterator to empty list.
Mar 19 23:01:50 :: WARNING: Attempting to remove iterator from NULL list.
Mar 19 23:01:50 :: WARNING: Attempting to remove contents that don't exist in list.
Mar 19 23:01:50 :: WARNING: Attempting to merge iterator to empty list.
Mar 19 23:01:50 :: WARNING: Attempting to remove iterator from NULL list.
Mar 19 23:01:50 :: WARNING: Attempting to remove contents that don't exist in list.

Program received signal SIGSEGV, Segmentation fault.
0x004e6d7a in next_in_list (pIterator=0x632cb0 <Iterator>) at lists.c:196
warning: Source file is more recent than executable.
196       pContent = pIterator->pItem ? pIterator->pItem->pContent : NULL;
(gdb) bt
#0  0x004e6d7a in next_in_list (pIterator=0x632cb0 <Iterator>) at lists.c:196
#1  0x004e6f5d in simple_list (pList=pList@entry=0x8003a2d0) at lists.c:274
#2  0x004e6ff6 in free_list (pList=0x8003a2d0) at lists.c:64
#3  0x0050456d in main (argc=2, argv=0x28ac2c) at comm.c:380
(gdb) info local
pTempItem = 0x61
(gdb) list
191       /* Cycle down the list */
192       pTempItem = pIterator->pItem->pNextItem;
193       pIterator->pItem = pTempItem;
194
195       /* Grab the content */
196       pContent = pIterator->pItem ? pIterator->pItem->pContent : NULL;
197
198       return (pContent);
199     }
200
(gdb) up
#1  0x004e6f5d in simple_list (pList=pList@entry=0x8003a2d0) at lists.c:274
274       if ((pContent = next_in_list(&Iterator)) != NULL)
(gdb) list
269           return (pContent);
270         } else
271           return NULL;
272       }
273
274       if ((pContent = next_in_list(&Iterator)) != NULL)
275         return (pContent);
276
277       remove_iterator(&Iterator);
278       loop = FALSE;
(gdb) info local
pContent = <optimized out>
(gdb) up
#2  0x004e6ff6 in free_list (pList=0x8003a2d0) at lists.c:64
64          while ((pContent = simple_list(pList)))
(gdb) list
59        void * pContent;
60
61        clear_simple_list();
62
63        if (pList->iSize)
64          while ((pContent = simple_list(pList)))
65            remove_from_list(pContent, pList);
66
67        if (pList->iSize > 0)
68          mudlog(CMP, LVL_GOD, TRUE, "List being freed while not empty.");
(gdb) info local
pContent = <optimized out>
(gdb) up
#3  0x0050456d in main (argc=2, argv=0x28ac2c) at comm.c:380
380         free_list(global_lists);
(gdb) list
375         free_save_list();       /* genolc.c */
376         free_strings(&config_info, OASIS_CFG); /* oasis_delete.c */
377         free_ibt_lists();       /* ibt.c */
378         free_recent_players();  /* act.informative.c */
379         free_list(world_events); /* free up our global lists */
380         free_list(global_lists);
381       }
382
383       if (last_act_message)
384         free(last_act_message);
(gdb) info local
pos = <optimized out>
dir = <optimized out>
(gdb) up
Initial frame selected; you cannot go up.
(gdb)

While pTempItem has a value plugged into it, I noticed that every variable that comes before it has been optimized out. Is this the source of the problem? This is going into another area I'm not too familiar with and don't quite understand. I know that you want to free up memory at times (including shutting down), and that if you start messing with a pointer that is pointing to nothing you're going to start having problems.

Also, I'm pretty sure this is just a different way to do an if statement, but it drives me crazy because I don't easily understand the syntax.
pContent = pIterator->pItem ? pIterator->pItem->pContent : NULL;

Any insight into this would be greatly appreciated. I'm not sure how I exactly screwed up, or where; the pItem makes me think that perhaps it has to do with some changes I've made to items (durability). Hard to say.

Please Log in or Create an account to join the conversation.

More
3 years 1 month ago #7741 by thomas
Replied by thomas on topic Crashing On Shutdown
Well, the ? : construct is called the ternary operator. There's a whole wikipedia page about it : en.wikipedia.org/wiki/%3F:

It is indeed shorthand for an if statement.
int foo;
if (condition)
  foo = x;
else
  foo = y;

vs.

int foo = condition ? x : y;
In some cases it makes the code easier to read, and in others, not so much. Avoid nesting them :S

value <optimized out> simply means that the compiler has determined that the actual value of whatever variable is not referenced in the given context, so it hasn't bothered to actually make it available. Sometimes you want - for debugging purposes, for instance - to have the values all present.
To make this work, you'll need to alter your Makefile so it doesn't trigger so much optimization. Simply remove the -O2 from your flags line.

In this case, you are likely crashing because something isn't set up correctly earlier on:
Mar 19 23:01:50 :: WARNING: Attempting to merge iterator to empty list.
Mar 19 23:01:50 :: WARNING: Attempting to remove iterator from NULL list.
Mar 19 23:01:50 :: WARNING: Attempting to remove contents that don't exist in list.
Mar 19 23:01:50 :: WARNING: Attempting to merge iterator to empty list.
Mar 19 23:01:50 :: WARNING: Attempting to remove iterator from NULL list.
Mar 19 23:01:50 :: WARNING: Attempting to remove contents that don't exist in list.
This looks quite strange to me; at this point, the lists should pretty well be pointing to something.

If this is a reproducible crash, I'd start by recompiling, starting, and connecting gdb to the process ("gdb bin/circle", then "attach <pid>" from within gdb. Add a breakpoint at where you are seeing the problem, "break comm.c:378", and trigger the problem.

This will allow you to debug the running code.
Interesting commands are "step" (steps into), "next" (steps over), "until" (steps over loops) and "finish" (steps out of). See ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_37.html#SEC38 . Also "print" which will print the value of anything following, for instance "print pContent" and "print *pContent".
My first plan would be to "next" until I see where those log statements come from...
The following user(s) said Thank You: Papaya Pete

Please Log in or Create an account to join the conversation.

  • Papaya Pete
  • Topic Author
  • Offline
  • Elite Member
  • Elite Member
More
3 years 1 month ago - 3 years 1 month ago #7764 by Papaya Pete
Replied by Papaya Pete on topic Crashing On Shutdown
Wow that makes ternary operators easier to understand! A newbie question however: I started doing the above steps (finally; I've been writing dialog and fixing little issues here and there before attempting to tackle this) and then realized I don't know what process ID I am supposed to become attached to. How would I find that out?

On a side note, I discovered a small bug that was giving a lot of errors and squashed it. Huzzah!

Edit:

I decided to repeat the previous action from before: up, list, info local. Here are the results of that:
Mar 23 00:53:48 :: WARNING: Attempting to merge iterator to empty list.
Mar 23 00:53:48 :: WARNING: Attempting to remove iterator from NULL list.
Mar 23 00:53:48 :: WARNING: Attempting to remove contents that don't exist in list.
Mar 23 00:53:48 :: WARNING: Attempting to merge iterator to empty list.
Mar 23 00:53:48 :: WARNING: Attempting to remove iterator from NULL list.
Mar 23 00:53:48 :: WARNING: Attempting to remove contents that don't exist in list.

Program received signal SIGSEGV, Segmentation fault.
0x0052c317 in next_in_list (pIterator=0x677c08 <Iterator>) at lists.c:196
196       pContent = pIterator->pItem ? pIterator->pItem->pContent : NULL;
(gdb) bt
#0  0x0052c317 in next_in_list (pIterator=0x677c08 <Iterator>) at lists.c:196
#1  0x0052c45e in simple_list (pList=0x8003a2d8) at lists.c:274
#2  0x0052bfce in free_list (pList=0x8003a2d8) at lists.c:64
#3  0x005244d1 in main (argc=2, argv=0x28ac2c) at comm.c:380
(gdb) info local
pContent = 0x49d8c7 <mudlog+16>
pTempItem = 0x61
(gdb) list
191       /* Cycle down the list */
192       pTempItem = pIterator->pItem->pNextItem;
193       pIterator->pItem = pTempItem;
194
195       /* Grab the content */
196       pContent = pIterator->pItem ? pIterator->pItem->pContent : NULL;
197
198       return (pContent);
199     }
200
(gdb) up
#1  0x0052c45e in simple_list (pList=0x8003a2d8) at lists.c:274
274       if ((pContent = next_in_list(&Iterator)) != NULL)
(gdb) list
269           return (pContent);
270         } else
271           return NULL;
272       }
273
274       if ((pContent = next_in_list(&Iterator)) != NULL)
275         return (pContent);
276
277       remove_iterator(&Iterator);
278       loop = FALSE;
(gdb) info local
pContent = 0x0
(gdb) up
#2  0x0052bfce in free_list (pList=0x8003a2d8) at lists.c:64
64          while ((pContent = simple_list(pList)))
(gdb) list
59        void * pContent;
60
61        clear_simple_list();
62
63        if (pList->iSize)
64          while ((pContent = simple_list(pList)))
65            remove_from_list(pContent, pList);
66
67        if (pList->iSize > 0)
68          mudlog(CMP, LVL_GOD, TRUE, "List being freed while not empty.");
(gdb) info local
pContent = 0x61282b68 <_gm_+136>
(gdb) up
#3  0x005244d1 in main (argc=2, argv=0x28ac2c) at comm.c:380
380         free_list(global_lists);
(gdb) list
375         free_save_list();       /* genolc.c */
376         free_strings(&config_info, OASIS_CFG); /* oasis_delete.c */
377         free_ibt_lists();       /* ibt.c */
378         free_recent_players();  /* act.informative.c */
379         free_list(world_events); /* free up our global lists */
380         free_list(global_lists);
381       }
382
383       if (last_act_message)
384         free(last_act_message);
(gdb) info local
pos = 1
dir = 0x8003a1d8 "lib"
(gdb) up
Initial frame selected; you cannot go up.
(gdb)

So this probably is just me, but this part right here doesn't look right.
277       remove_iterator(&Iterator);
278       loop = FALSE;
(gdb) info local
pContent = 0x0   <<<<<<---------------------------------
(gdb) up
#2  0x0052bfce in free_list (pList=0x8003a2d8) at lists.c:64
64          while ((pContent = simple_list(pList)))

Wouldn't 0x0 mean no value? Or is this just read/interpreted differently because it's dealing with memory? If this is supposed to mean NULL, that could be a problem. Will take another look when I'm not tired.
Last edit: 3 years 1 month ago by Papaya Pete.

Please Log in or Create an account to join the conversation.

More
3 years 1 month ago #7777 by thomas
Replied by thomas on topic Crashing On Shutdown
You are right, 0x0 is a null pointer. But it's NULL because the assignment on that line hasn't happened yet.

What seems to be occurring is that the global_lists variable seem to be messed up.
I think this is more serious:
pTempItem = 0x61
This is supposed to be a pointer to the stored item. It obviously isn't. So, somewhere, there's an iff by one (or more) error. Finding that one is somewhat harder.

Please Log in or Create an account to join the conversation.

  • Papaya Pete
  • Topic Author
  • Offline
  • Elite Member
  • Elite Member
More
3 years 1 month ago #7778 by Papaya Pete
Replied by Papaya Pete on topic Crashing On Shutdown
I have a possible theory as to how it started. I'm going to plug the item durability snippet into a fresh batch of stock code and see if the problem comes up. If it does, I have an idea where to start. If not, more digging!

Please Log in or Create an account to join the conversation.

  • Papaya Pete
  • Topic Author
  • Offline
  • Elite Member
  • Elite Member
More
3 years 1 month ago #7784 by Papaya Pete
Replied by Papaya Pete on topic Crashing On Shutdown
So my bit of digging shows that the item durability snippet doesn't seem to be the problem; I plugged it into the stock tbamud code and no issues. I've been trying to go through the above process mentioned (break comm.c:379, step, info local, print) to try and figure out what's going on. It's not really making a whole lot of sense. I wish I could tell what exactly is in these different variables; does it have to do with the player files? Objects? Mobs?

Honestly, I'm not really sure what free_list(global_lists) even does. Hah, it would help if I understood what exactly the error was in the first place in order to fix it! What global variables does it deal with? Would taking out stock areas possibly cause an error like this? There's still a lot to tbamud (and coding in general) I don't understand. I'll be doing some reading here and there to see if I can get some answers, but any input would be appreciated; thank you for patiently answering my questions!

As much work as it would be, I'm sort of tempted to try plugging in all of my snippets into a fresh batch of code, one by one, and see if one of them is the problem. The talk and ask chain will be very difficult, because (thanks to me walking away from coding for a few months) I can't remember exactly all the work that went into it.

Side note: rebooting the mud does NOT trigger the crash. "Shutdown" and "shutdown die" do trigger it. I suppose that narrows it down slightly!

Please Log in or Create an account to join the conversation.

More
3 years 2 weeks ago - 3 years 2 weeks ago #7999 by Krell
Replied by Krell on topic Crashing On Shutdown

Honestly, I'm not really sure what free_list(global_lists) even does. Hah, it would help if I understood what exactly the error was in the first place in order to fix it! What global variables does it deal with?


global_lists is struct of type char that is created using create_list() when the mud is first started up. free_lists() is called to free and NULL the addresses used by global_lists upon shutdown.

Side note: rebooting the mud does NOT trigger the crash. "Shutdown" and "shutdown die" do trigger it. I suppose that narrows it down slightly!


Yes, if global_lists is using addresses it isn't supposed to then it'll show up on shutdown when free_lists() is called. I believe a simple reboot or copyover doesn't require clearing all memory, though you'd think a reboot should. Maybe there's some sort of speedup involved by NOT clearing out all memory on reboot?

I've had, and continue to have, a similar issue on shutdown except my problem shows up in clearing out the followers lists. So I never even get to that section in comm.c.

Edit: Actually, create_list() is a struct of type list_data*, not char*.

Edit 2: Just in case my tone seems to indicate otherwise, I'm not an expert but this is what I believe I've figured out while trying to debug my own crashing on shutdown issue. Take everything I say with a helping of NaCl.
Last edit: 3 years 2 weeks ago by Krell.

Please Log in or Create an account to join the conversation.

Time to create page: 0.105 seconds