View Issue Details

IDProjectCategoryView StatusLast Update
0003039FSSCPBuild systempublic2014-05-22 18:37
Reporterz64555 Assigned To 
PriorityhighSeverityminorReproducibilityrandom
Status resolvedResolutionfixed 
Platformx86_64OSMicrosoft WindowsOS Version8.1
Product Version3.7.2 RC1 
Target Version3.7.2 
Summary0003039: Debug Console Commands Sometimes Don't Show Up
DescriptionCame across this issue some time ago when initially working with the debug console. Essentially, a number of DCF's defined in the FSO code base are not being added to the command list. If they're not on the command list, then a user cannot see nor use them from the debug console.
Steps To Reproduce1. Run any build post-r10622.

2. Get to the login screen, and press Shift + Enter to bring up the debug console.

3. Enter 'help' into the debug console to bring up the help screen. A list of available commands should be shown.

4. Note the number of available commands. There should be over 100 of them.
Additional InformationI have a suspicion that this is build related, and that the DCF's are getting optimized out somehow.

Another suspicion is that they're just not getting added to the list properly. I may have to consider using a different method of declaring and adding the DCF's.
TagsNo tags attached.

Activities

z64555

2014-05-07 18:27

developer   ~0015724

Issue seems to be related to the tool used to build it. Chief and I have confirmed all/most of the DCFs are properly added for MSVS 2012, and for OSX.

VC2008 is confirmed to have the issue, haven't tried VC2010 or VC6 yet.

chief1983

2014-05-07 19:12

administrator   ~0015725

I am going to try VC6 if the last commit fixed compiling with it.

niffiwan

2014-05-08 10:39

developer   ~0015726

Last edited: 2014-05-08 12:39

FYI, on Linux (gcc 4.6.3) the help list starts with "medals" and is only slightly longer than one page so it would seem that not all DCFs are being loaded. However, I can run (for instance) run "cscrew" and get output. Does that mean the problem is only with help, and not loading then DCFs?

edit: Oops. Didn't realise you can scroll up with PgUp. If I do that I think I get the complete list. However there may be an issue with the paging?

chief1983

2014-05-08 15:16

administrator   ~0015727

Last edited: 2014-05-08 16:32

Yeah I thought the paging was behaving oddly on some platforms too. On OS X I think I got correct paging, and on Windows I think I just got the behavior you got. I may have that reversed though.

Edit: Ok yeah, just tested OS X again. At 640x480, the first command is Change...something, and I have the option to see 'More' twice, so it takes 3 pages to show what seems to be everything. The Windows VC2012 build must be the one that didn't paginate for me yesterday.

z64555

2014-05-08 20:11

developer   ~0015729

Just to clarify the paginate issues, could you link a screenshot of what's happening?

chief1983

2014-05-08 20:39

administrator   ~0015730

I assume that paginating the help results, and not just dumping them all and then requiring you to scroll back up to read them, is the correct behavior? The one I saw misbehaving is at home, I'll try to get screenshots tonight. Maybe even record it.

z64555

2014-05-09 11:10

developer   ~0015733

Original behavior was to dump the help results until it filled up the buffer. Since that seems to be unintuitive, the behavior has been changed to fill up the screen before pausing the output.

Note that this behavior is only limited to --help, if other commands wish to do the same then they will have to copy the for loop... or make another accessory function around the for loop and use that.

z64555

2014-05-21 01:50

developer  

m3039.patch (7,795 bytes)   
From b405c1c84b4119aa7f4e1506802c64d9745cfd68 Mon Sep 17 00:00:00 2001
From: z64555 <z1281110@gmail.com>
Date: Tue, 20 May 2014 20:57:13 -0500
Subject: [PATCH] Fixes 3039: C++ stdlib was having data race issues with
 instanciating the debug_commands and the vector that was supposed to contain
 them. Seems like :v: ran into this issue a few times before...

---
 code/debugconsole/console.cpp     | 19 +++++-----
 code/debugconsole/console.h       |  5 +++
 code/debugconsole/consolecmds.cpp | 79 +++++++++++++++++++++++++++++----------
 3 files changed, 74 insertions(+), 29 deletions(-)

diff --git a/code/debugconsole/console.cpp b/code/debugconsole/console.cpp
index b7eb607..c7acecb 100644
--- a/code/debugconsole/console.cpp
+++ b/code/debugconsole/console.cpp
@@ -138,8 +138,9 @@ void dc_do_command(SCP_string *cmd_str)
 	 *      Call the function to process the command (the rest of the command line is in the parser)
 	 *          Function takes care of long_help and status depending on the mode.
 	 */
+	int i;
 	SCP_string command;
-	extern SCP_vector<debug_command*> dc_commands;	// z64: I don't like this extern here, at all. Nope nope nope.
+	extern debug_command* dc_commands[];	// z64: I don't like this extern here, at all. Nope nope nope.
 
 	if (cmd_str->empty()) {
 		return;
@@ -149,15 +150,20 @@ void dc_do_command(SCP_string *cmd_str)
 
 	dc_stuff_string_white(command);		// Grab the first token, presumably this is a command
 
-	SCP_vector<debug_command*>::iterator it = std::find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(command.c_str()));
+	for (i = 0; i < dc_commands_size; ++i) {
+
+		if (stricmp(dc_commands[i]->name, command.c_str()) == 0) {
+			break;
+		} // Else, continue
+	}
 
-	if (it == dc_commands.end()) {
+	if (i == dc_commands_size) {
 		dc_printf("Command not found: '%s'\n", command.c_str());
 		return;
 	} // Else, we found our command
 
 	try {
-		(*it)->func();	// Run the command!
+		dc_commands[i]->func();	// Run the command!
 	
 	} catch (errParseString err) {
 		dc_printf("Require string(s) not found: \n");
@@ -267,17 +273,12 @@ void dc_draw_window(bool show_prompt)
 
 void dc_init(void)
 {
-	extern SCP_vector<debug_command*> dc_commands;
-
 	if (debug_inited) {
 		return;
 	}
 
 	debug_inited = TRUE;
 
-	// Sort debug_commands
-	std::sort(dc_commands.begin(), dc_commands.end(), dcmd_less);
-
 	// Init window settings
 	dc_font = FONT1;
 	row_height = ((Current_font->h) * 3) / 2;	// Row/Line height, in pixels
diff --git a/code/debugconsole/console.h b/code/debugconsole/console.h
index 867a979..c8abde1 100644
--- a/code/debugconsole/console.h
+++ b/code/debugconsole/console.h
@@ -22,6 +22,8 @@
 #include "globalincs/pstypes.h"
 #include "globalincs/vmallocator.h"
 
+#define DC_MAX_COMMANDS 300
+
 class debug_command;
 
 /**
@@ -222,6 +224,8 @@ public:
 	const char *help;		//!< The short help string, as shown by 'help <command>'
 	void (*func)();	//!< Pointer to the function that to run when this command is evoked
 
+	debug_command();
+
 	/**
 	* @brief Adds a debug command to the debug_commands map, if it isn't in there already.
 	*
@@ -248,6 +252,7 @@ public:
 };
 
 extern bool Dc_debug_on;
+extern int dc_commands_size;
 extern uint lastline;
 extern SCP_string dc_command_str;	// The rest of the command line, from the end of the last processed arg on.
 
diff --git a/code/debugconsole/consolecmds.cpp b/code/debugconsole/consolecmds.cpp
index 8d511b6..46e533a 100644
--- a/code/debugconsole/consolecmds.cpp
+++ b/code/debugconsole/consolecmds.cpp
@@ -26,8 +26,8 @@
 #include <algorithm>
 
 // ========================= GLOBALS =========================
-SCP_vector<debug_command*> dc_commands;
-typedef SCP_vector<debug_command*>::iterator dc_commands_it;
+debug_command *dc_commands[DC_MAX_COMMANDS];
+int dc_commands_size = 0;
 
 // ========================= LOCALS ==========================
 // dcf_shell commands
@@ -36,23 +36,53 @@ void dc_shell_resize( void );
 void dc_shell_resize_buf( void );
 
 // =================== class debug_command ===================
-debug_command::debug_command(const char *_name, const char *_help, void (*_func)())
-	: name(_name), help(_help), func(_func)
-{
-	dc_commands_it it = std::find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(_name));
-	
-	if (it != dc_commands.end()) {
-		Int3();		// Command already exists! Somebody didn't use the DCF macro as they should've...
+debug_command::debug_command()
+: name(""), help(""), func(NULL) {
+};
+
+debug_command::debug_command(const char *_name, const char *_help, void(*_func)())
+	: name(_name), help(_help), func(_func) {
+	int i = 0;
+	int ret = 0;
+
+	if (dc_commands_size > DC_MAX_COMMANDS) {
+		Error(LOCATION, "Too many debug console commands! Please inform a coder to increase DC_MAX_COMMANDS.");
+		return;
 	}
 
-	dc_commands.push_back(this);
+	// Start the insertion sort by finding where to stick the debug command
+	for (; i < dc_commands_size; ++i) {
+		ret = stricmp(dc_commands[i]->name, _name);
+
+		if (ret == 0) {
+			Error(LOCATION, "Debug Command %s already exists! Please inform a coder immediately.", _name);
+			return;
+		} else if (ret > 0) {
+			// Insert the command here
+			break;
+		} // Else, do nothing
+	}
+
+	// Then, do the insertion
+	if (i < dc_commands_size) {
+		for (int j = dc_commands_size; j > i; --j) {
+			dc_commands[j] = dc_commands[j - 1];
+		}
+		dc_commands[i] = this;
+		dc_commands_size++;
+	} else {
+		dc_commands[dc_commands_size] = this;
+		dc_commands_size++;
+	}
 }
 
 // ============================== IMPLEMENTATIONS =============================
 
 DCF(debug, "Runs a command in debug mode.")
 {
+	int i;
 	SCP_string command = "";
+	
 	Dc_debug_on = true;
 
 	dc_stuff_string_white(command);
@@ -62,16 +92,20 @@ DCF(debug, "Runs a command in debug mode.")
 		return;
 	} // Else, command is present.
 
-	dc_commands_it it = std::find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(command.c_str()));
+	for (i = 0; i < dc_commands_size; ++i) {
+		if (stricmp(dc_commands[i]->name, command.c_str()) == 0) {
+			break;
+		} // Else, continue
+	}
 
-	if (it == dc_commands.end()) {
+	if (i == dc_commands_size) {
 		dc_printf("<debug> Command not found: '%s'\n", command.c_str());
 		return;
-	} // Else, command exists. Run it.
+	} // Else, we found our command
 
 	dc_printf("<debug> Executing command: '%s'\n", command.c_str());
 	// try {
-	(*it)->func();
+	dc_commands[i]->func();
 	// } catch {
 	// }
 
@@ -82,6 +116,7 @@ DCF(help, "Displays the help list." )
 {
 	extern uint DROWS;
 
+	int i;
 	SCP_string command = "";
 
 	dc_maybe_stuff_string_white(command);
@@ -92,14 +127,18 @@ DCF(help, "Displays the help list." )
 		return;
 
 	} else if (command != "") {
-		dc_commands_it it = std::find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(command.c_str()));
+		for (i = 0; i < dc_commands_size; ++i) {
+			if (stricmp(dc_commands[i]->name, command.c_str()) == 0) {
+				break;
+			} // Else, continue
+		}
 
-		if (it == dc_commands.end()) {
+		if (i == dc_commands_size) {
 			dc_printf("Command not found: '%s'\n", command.c_str());
 			return;
-		}
+		} // Else, we found our command
 
-		dc_printf("%s\n", (*it)->help);
+		dc_printf("%s\n", dc_commands[i]->help);
 		return;
 	} // Else, command line is empty, print out the help list
 
@@ -111,12 +150,12 @@ DCF(help, "Displays the help list." )
 	dc_printf("\n");
 
 	dc_printf(" Available commands:\n");
-	for (dc_commands_it it = dc_commands.begin(); it != dc_commands.end(); ++it) {
+	for (i = 0; i < dc_commands_size; ++i) {
 		if (((lastline % DROWS) == 0) && (lastline != 0)) {
 			dc_pause_output();
 		}
 
-		dc_printf(" %s - %s\n", (*it)->name, (*it)->help);
+		dc_printf(" %s - %s\n", dc_commands[i]->name, dc_commands[i]->help);
 	}
 }
 
-- 
1.8.3.msysgit.0

m3039.patch (7,795 bytes)   

z64555

2014-05-21 01:52

developer   ~0015753

Issue appears to have been more of an issue with stdlib rather than the build system. std::vector might've gotten an update sometime between VS2008 and 2010, hence why the issue was only showing up on VS2008 and VC6.

I've attached a patch which reverts to the old method of using an array instead of one of the dynamic containers, since it works so well.

niffiwan

2014-05-21 21:05

developer   ~0015754

The patch fixes the issue I had on Centos 6 with gcc 4.4.7

chief1983

2014-05-22 15:47

administrator   ~0015755

Last edited: 2014-05-22 15:47

Yeah, seems to fix VC2008 too. Go ahead and commit whenever, unless we're waiting on any other code review.

z64555

2014-05-22 18:37

developer   ~0015756

Fix committed to trunk@10712.

Related Changesets

fs2open: trunk r10712

2014-05-22 13:51

z64555


Ported: N/A

Details Diff
Fixes 3039: C++ STL was having data race issues with instantiating the debug_commands and the vector that was supposed to reference them. Seems like :v: ran into this issue a few times before... Affected Issues
0003039
mod - /trunk/fs2_open/code/debugconsole/console.cpp Diff File
mod - /trunk/fs2_open/code/debugconsole/console.h Diff File
mod - /trunk/fs2_open/code/debugconsole/consolecmds.cpp Diff File

Issue History

Date Modified Username Field Change
2014-05-07 16:25 z64555 New Issue
2014-05-07 16:25 z64555 Status new => assigned
2014-05-07 16:25 z64555 Assigned To => chief1983
2014-05-07 18:27 z64555 Note Added: 0015724
2014-05-07 19:12 chief1983 Note Added: 0015725
2014-05-08 10:39 niffiwan Note Added: 0015726
2014-05-08 12:39 niffiwan Note Edited: 0015726
2014-05-08 15:16 chief1983 Note Added: 0015727
2014-05-08 16:32 chief1983 Note Edited: 0015727
2014-05-08 20:11 z64555 Note Added: 0015729
2014-05-08 20:39 chief1983 Note Added: 0015730
2014-05-09 11:10 z64555 Note Added: 0015733
2014-05-21 01:50 z64555 File Added: m3039.patch
2014-05-21 01:52 z64555 Note Added: 0015753
2014-05-21 01:53 z64555 Assigned To chief1983 =>
2014-05-21 01:53 z64555 Status assigned => code review
2014-05-21 21:05 niffiwan Note Added: 0015754
2014-05-22 15:47 chief1983 Note Added: 0015755
2014-05-22 15:47 chief1983 Note Edited: 0015755
2014-05-22 18:37 z64555 Changeset attached => fs2open trunk r10712
2014-05-22 18:37 z64555 Note Added: 0015756
2014-05-22 18:37 z64555 Status code review => resolved
2014-05-22 18:37 z64555 Resolution open => fixed