GNOME Bugzilla – Bug 395447
gnobots2 uses 100% CPU
Last modified: 2007-07-13 01:05:26 UTC
Please describe the problem: gnubots uses 100% of the CPU untill killed/closed without achieving anything. Guess that this happens when there are no safe teleporting destinations available, and some routine randomly tries to reposition repeatedly without ever detecting that no options are available. Maybe a check for this condition should be added. Steps to reproduce: 1. Play the game 2. When there are no safe teleporting locations, click on "Teleport" 3. Actual results: gnubots2 uses 100% of the CPU, and nothing happens. (Desktop and other programs still responsive). Don't remember if I had to kill gnubots2, or if it was possible to close it normally. Expected results: 1) Newer use 100% cpu indefinitely, when all positions tried and no safe found, bail out. 2) Current score should at least be saved to highscore if it belongs there (not the case currently) 3) EITHER a message ("There are no safe teleporting locations, you have run out of luck") OR possibility to retry that level Does this happen every time? Yes (when steps for reproduction followed, but that could take weeks) No (during normal usage, has only occured once for me so far). Other information: Screenshot of playing field when it happend: http://www.simong.se/short-term-storage/delete-june-2007/robots-hang-cpu100.png
100% CPU usage happened again. I have to revise the "could take weeks" to reproduce into "problem occurs several times a week". I can also add that it's not possible to quit the program at all, it has to be killed (either kill or "Force Quit" in the "program not responding" dialog). This time I installed relevant debuginfo-packages, and attached gdb to the running gnobots2. Can attach a stack trace, core dump, and another screen shot if wanted, but the problem was clearest when stepping around with gdb, so I'll start there. Playing in gdb shows that the code is stuck in an infinite loop at lines 1243-1266 in game.c (see excerpt at bottom). To get there, one has to pass the check at lines 1212-1225. That check is newer even executed when "super safe moves" isn't selected. But I had "super safe moves" enabled, so the check at lines 1212-1225 didn't detect that there are no safe moves, and one then gets stuck in the "while (1) {" beginning at line 1243. Proposed solutions: (if problem still persists in newest version) Alternative 1) Write a working check at lines 1212-1225, and add an additional check when "super safe moves" isn't selected. This feels like a proper solution, but harder to verify. Alternative 2) in the source, change 1243 while (1) { <SNIP> 1255 break; <SNIP> 1266 } into something more like this 1243a int success=0; 1243b do { <SNIP> 1255a success=1; 1255b break; <SNIP> 1266a } while( (ixp!=xp) && (iyp!=yp) ); 1266b if( !success ){ 1266c message_box (_("You have run out of safe moves - the robots have won!")); 1266d kill_player (); 1266e return FALSE; 1266f } This would give up looking for safe teleport locations when all has been tried, and might be useful as an additional check even if the first solution is attempted (this is simple, catches this 100% cpu usage problem, as well as notifies the user and permits saving of the high score) I don't have time to write a proper patch (something i'we newer done before) especially when there is a new version out there which I don't have time / motivation to debug as well, but if there still is no check preventing the infinite lock at all when "super safe moves" are disabled (see line 1212), this issue should be handled by somebody. Excerpt from game.c for gnobots2 version 2.16.0 1197 /** 1198 * safe_teleport 1199 * 1200 * Description: 1201 * teleports the player to safe location 1202 * 1203 * Returns: 1204 * TRUE if player can be teleported, FALSE otherwise 1205 **/ 1206 static gboolean 1207 safe_teleport (void) 1208 { 1209 gint xp, yp, ixp, iyp; 1210 gint i, j; 1211 1212 if (properties_super_safe_moves () && !safe_teleport_available ()) { 1213 /* FIXME: This code is untested - in normal play you have to get to 1214 * about level 61. */ 1215 if (!safe_move_available ()) { 1216 message_box (_("You have run out of safe moves - the robots have won!")); 1217 kill_player (); 1218 return FALSE; 1219 } else if (safe_teleports > 0) { 1220 message_box (_("There are no safe locations to teleport to!!")); 1221 return FALSE; 1222 } else { 1223 return random_teleport (); 1224 } 1225 } 1226 1227 if (safe_teleports <= 0) 1228 return random_teleport (); 1229 1230 for (i = 0; i < GAME_WIDTH; ++i) { 1231 for (j = 0; j < GAME_HEIGHT; ++j) { 1232 if (arena[i][j] != OBJECT_PLAYER) { 1233 temp_arena[i][j] = arena[i][j]; 1234 } else { 1235 temp_arena[i][j] = OBJECT_NONE; 1236 } 1237 } 1238 } 1239 1240 ixp = xp = rand () % GAME_WIDTH; 1241 iyp = yp = rand () % GAME_HEIGHT; 1242 1243 while (1) { 1244 1245 if ((temp_arena[xp][yp] == OBJECT_NONE) && check_safe (xp, yp)) { 1246 player_xpos = xp; 1247 player_ypos = yp; 1248 temp_arena[player_xpos][player_ypos] = OBJECT_PLAYER; 1249 1250 reset_player_animation (); 1251 1252 safe_teleports -= 1; 1253 1254 update_arena (); 1255 break; 1256 } 1257 1258 ++xp; 1259 if (xp >= GAME_WIDTH) { 1260 xp = 0; 1261 ++yp; 1262 if (yp >= GAME_HEIGHT) { 1263 yp = 0; 1264 } 1265 } 1266 } 1267 1268 remove_splat_bubble (); 1269 play_sound (SOUND_TELEPORT); 1270 1271 return TRUE; 1272 } BTW Ctrl-w to cut lines in xemacs don't blend well with mozilla - had to rewrite most of this when I accidentally closed the browser-tab.
Took a quick look at the latest CVS version, and it seems like the check at lines 1212-1225 (se comment above) might be working in the newest version because of changes to resolve bug #353303 (havn't confirmed that thou). BUT the check at lines 1212-1225 (in both the 2.16.0 version and current CVS version) to avoid the infinite loop is still bypassed if "super safe moves" isn't selected, so the application would still stuck at 100% cpu usage if one would manage to play long enough with "super safe moves" disabled.
This was fixed in bug #438829 by simply killing the player if no safe teleport locations are available.