diff: fix mdb I/O interleaving bug

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Feb 5 07:34:07 AEDT 1999


Estimated hours taken: 0.5

Fix a bug with I/O interleaving which was causing some of the
debugger test cases to fail.

trace/mercury_trace_internal.c:
	Ensure that MR_mdb_err is unbuffered, and that we always
	fflush(MR_mdb_out) before writing to MR_mdb_out.

Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.21
diff -u -r1.21 mercury_trace_internal.c
--- mercury_trace_internal.c	1998/12/28 03:38:53	1.21
+++ mercury_trace_internal.c	1999/02/04 20:29:44
@@ -64,6 +64,13 @@
 ** the distinction between stdout and stderr: ordinary output, including
 ** information messages about conditions which are not errors, should
 ** go to MR_mdb_out, but error messages should go to MR_mdb_err.
+**
+** Note that MR_mdb_out and MR_mdb_err may both write to the same
+** file, so we need to be careful to ensure that buffering does
+** not stuff up the interleaving of error messages and ordinary output.
+** To ensure this, we do two things:
+**	- MR_mdb_err is unbuffered
+**	- we always fflush(MR_mdb_out) before writing to MR_mdb_err
 */
 FILE *MR_mdb_in;
 FILE *MR_mdb_out;
@@ -319,6 +326,9 @@
 		MR_mdb_out = MR_try_fopen(MR_mdb_out_filename, "w", stdout);
 		MR_mdb_err = MR_try_fopen(MR_mdb_err_filename, "w", stderr);
 
+		/* Ensure that MR_mdb_err is not buffered */
+		setvbuf(MR_mdb_err, NULL, _IONBF, 0);
+
 		if (getenv("MERCURY_SUPPRESS_MDB_BANNER") == NULL) {
 			fprintf(MR_mdb_out, MR_trace_banner, MR_VERSION);
 		}
@@ -389,6 +399,7 @@
 static void
 MR_trace_do_noop(void)
 {
+	fflush(MR_mdb_out);
 	fprintf(MR_mdb_err,
 		"This command is a no-op from this port.\n");
 }
@@ -451,6 +462,7 @@
 
 	problem = MR_trace_parse_line(line, &words, &word_max, &word_count);
 	if (problem != NULL) {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "%s.\n", problem);
 		goto return_keep_interacting;
 	}
@@ -479,6 +491,7 @@
 			cmd->MR_trace_print_level = MR_default_print_level;
 			goto return_stop_interacting;
 		} else {
+			fflush(MR_mdb_out);
 			fprintf(MR_mdb_err, "One of the first two words "
 				"must be a command.\n");
 		}
@@ -516,6 +529,7 @@
 				goto return_stop_interacting;
 			} else {
 				/* XXX this message is misleading */
+				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err, "The debugger cannot go "
 					"to a past event.\n");
 			}
@@ -775,6 +789,7 @@
 					MR_saved_curfr(saved_regs),
 					include_trace_data);
 			if (msg != NULL) {
+				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err, "%s.\n", msg);
 			}
 		} else {
@@ -824,6 +839,7 @@
 					MR_trace_internal_add_spy_point(when,
 						action, spy_proc, NULL);
 				} else {
+					fflush(MR_mdb_out);
 					fprintf(MR_mdb_err,
 						"Ambiguous procedure "
 						"specification. "
@@ -845,6 +861,7 @@
 				MR_spy_points[n]->spy_enabled = TRUE;
 				MR_print_spy_point(n);
 			} else {
+				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err,
 					"Break point #%d does not exist.\n",
 					n);
@@ -868,6 +885,7 @@
 				MR_spy_points[n]->spy_enabled = FALSE;
 				MR_print_spy_point(n);
 			} else {
+				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err,
 					"Break point #%d does not exist.\n",
 					n);
@@ -879,6 +897,7 @@
 			}
 
 			if (MR_spy_point_next == 0) {
+				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err,
 					"There are no break points yet.\n");
 			}
@@ -1050,6 +1069,7 @@
 						words[1]);
 				}
 			} else {
+				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err,
 					"Alias `%s' cannot be removed, "
 					"since it does not exist.\n",
@@ -1071,6 +1091,7 @@
 		} else {
 			msg = MR_trace_add_cat(words[2], slot, help_text);
 			if (msg != NULL) {
+				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err,
 					"Document category `%s' not added: "
 					"%s.\n", words[2], msg);
@@ -1090,6 +1111,7 @@
 			msg = MR_trace_add_item(words[1], words[3], slot,
 				help_text);
 			if (msg != NULL) {
+				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err,
 					"Document item `%s' in category `%s' "
 					"not added: %s.\n",
@@ -1230,6 +1252,7 @@
 			MR_trace_usage("misc", "quit");
 		}
 	} else {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "Unknown command `%s'. "
 			"Give the command `help' for help.\n", words[0]);
 	}
@@ -1458,7 +1481,7 @@
 MR_trace_usage(const char *cat, const char *item)
 /* cat is unused now, but could be used later */
 {
-
+	fflush(MR_mdb_out);
 	fprintf(MR_mdb_err,
 		"mdb: %s: usage error -- type `help %s' for help.\n",
 		item, item);
@@ -1483,6 +1506,7 @@
 	call_label = entry->MR_sle_call_label;
 
 	if (call_label->MR_sll_var_count < 0) {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err,
 			"Cannot perform retry, because information about "
 			"the input arguments is not available.\n");
@@ -1507,6 +1531,7 @@
 				input_args->MR_slvs_names[i], &succeeded);
 
 		if (! succeeded) {
+			fflush(MR_mdb_out);
 			fprintf(MR_mdb_err,
 				"Cannot perform retry because the values of "
 				"some input arguments are missing.\n");
@@ -1662,12 +1687,14 @@
 				&base_sp, &base_curfr, &problem);
 
 	if (level_layout == NULL) {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "%s\n", problem);
 		return;
 	}
 
 	problem = MR_trace_validate_var_count(level_layout, &var_count);
 	if (problem != NULL) {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 		return;
 	}
@@ -1692,6 +1719,7 @@
 		fprintf(MR_mdb_out, "Ancestor level set to %d.\n",
 			*ancestor_level);
 	} else {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "%s.\n", problem);
 	}
 }
@@ -1745,12 +1773,14 @@
 				&base_sp, &base_curfr, &problem);
 
 	if (level_layout == NULL) {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 		return;
 	}
 
 	problem = MR_trace_find_var(level_layout, var_spec, &which_var);
 	if (problem != NULL) {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 		return;
 	}
@@ -1790,12 +1820,14 @@
 				&base_sp, &base_curfr, &problem);
 
 	if (level_layout == NULL) {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 		return;
 	}
 
 	problem = MR_trace_validate_var_count(level_layout, &var_count);
 	if (problem != NULL) {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 		return;
 	}
@@ -2201,6 +2233,7 @@
 		fclose(fp);
 		return TRUE;
 	} else {
+		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "%s: %s.\n", filename, strerror(errno));
 		return FALSE;
 	}
@@ -2387,6 +2420,7 @@
 								max_mr_num);
 
 					default:
+						fflush(MR_mdb_out);
 						fprintf(MR_mdb_err,
 							"unknown command, "
 							"try again\n");

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "Binaries may die
WWW: <http://www.cs.mu.oz.au/~fjh>  |   but source code lives forever"
PGP: finger fjh at 128.250.37.3        |     -- leaked Microsoft memo.



More information about the developers mailing list