[m-dev.] diff: fix bug in io__make_temp

Fergus Henderson fjh at cs.mu.OZ.AU
Sun Oct 3 20:40:29 AEST 1999


Estimated hours taken: 1

Fix a bug introduced by my change to make the I/O library handle
errors by throwing exceptions.  There was some pragma c_code which
was declared `may_call_mercury', since it can throw an exception,
but which allocated memory using incr_hp(), which assumes that the
hp register is valid, and the hp register is not valid in registers
declared `may_call_mercury'.  This broke the test case
tests/hard_coded/remove_file.m in non-gc grades.

library/io.m:
	change the code for io__make_temp/5 so that the C code
	does not throw an exception by calling back Mercury,
	but instead just returns an error indicator back to
	Mercury code which throws the exception.  This allows
	it to be declared `will_not_call_mercury' again,
	which avoids the problem with the hp register not being
	valid in code declared `may_call_mercury'.
	
	Also add some comments to ML_maybe_make_err_msg()
	to reduce the likelihood of similar bugs in the future,
	and rename the `len' variable there as `total_len',
	to avoid a warning from `gcc -Wshadow'.

Workspace: /home/mercury0/fjh/mercury
Index: library/io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.184
diff -u -r1.184 io.m
--- io.m	1999/09/30 22:07:47	1.184
+++ io.m	1999/10/03 10:36:54
@@ -3314,8 +3314,19 @@
 	),
 	io__make_temp(Dir, "mtmp", Name).
 
+io__make_temp(Dir, Prefix, Name) -->
+	io__do_make_temp(Dir, Prefix, Name, Err, Message),
+	{ Err \= 0 ->
+		throw_io_error(Message)
+	;
+		true
+	}.
+
 /*---------------------------------------------------------------------------*/
 
+:- pred io__do_make_temp(string, string, string, int, string, io__state, io__state).
+:- mode io__do_make_temp(in, in, out, out, out, di, uo) is det.
+
 /*
 ** XXX	The code for io__make_temp assumes POSIX.
 **	It uses the functions open(), close(), and getpid()
@@ -3341,9 +3352,9 @@
 	long	ML_io_tempnam_counter = 0;
 ").
 
-:- pragma c_code(io__make_temp(Dir::in, Prefix::in, FileName::out,
-		IO0::di, IO::uo),
-		[may_call_mercury, thread_safe],
+:- pragma c_code(io__do_make_temp(Dir::in, Prefix::in, FileName::out,
+		Error::out, ErrorMessage::out, IO0::di, IO::uo),
+		[will_not_call_mercury, thread_safe],
 "{
 	/*
 	** Constructs a temporary name by concatenating Dir, `/',
@@ -3379,15 +3390,14 @@
 	} while (fd == -1 && errno == EEXIST &&
 		num_tries < MAX_TEMPNAME_TRIES);
 	if (fd == -1) {
-		mercury_io_error(NULL,
-			""error opening temporary file `%s': %s"",
-			FileName, strerror(errno));
-	} 
-	err = close(fd);
-	if (err != 0) {
-		mercury_io_error(NULL,
-			""error closing temporary file `%s': %s"",
-			FileName, strerror(errno));
+		ML_maybe_make_err_msg(TRUE, ""error opening temporary file"",
+			MR_PROC_LABEL, ErrorMessage);
+		Error = -1;
+	}  else {
+		err = close(fd);
+		ML_maybe_make_err_msg(err, ""error closing temporary file"",
+			MR_PROC_LABEL, ErrorMessage);
+		Error = err;
 	}
 	update_io(IO0, IO);
 }").
@@ -3400,27 +3410,31 @@
 #include <errno.h>
 
 /*
-** ML_maybe_make_err_msg(was_error, msg, error_msg):
+** ML_maybe_make_err_msg(was_error, msg, procname, error_msg):
 **	if `was_error' is true, then append `msg' and `strerror(errno)'
 **	to give `error_msg'; otherwise, set `error_msg' to NULL.
 **
+** WARNING: this must only be called when the `hp' register is valid.
+** That means it must only be called from procedures declared
+** `will_not_call_mercury'.
+**
 ** This is defined as a macro rather than a C function
 ** to avoid worrying about the `hp' register being
 ** invalidated by the function call.
 ** It also needs to be a macro because incr_hp_atomic_msg()
-** stringizes its third argument.
+** stringizes the procname argument.
 */
 #define ML_maybe_make_err_msg(was_error, msg, procname, error_msg)	\\
 	do {								\\
 		char *errno_msg;					\\
-		size_t len;						\\
+		size_t total_len;					\\
 		Word tmp;						\\
 									\\
 		if (was_error) {					\\
 			errno_msg = strerror(errno);			\\
-			len = strlen(msg) + strlen(errno_msg);		\\
+			total_len = strlen(msg) + strlen(errno_msg);	\\
 			incr_hp_atomic_msg(tmp,				\\
-				(len + sizeof(Word)) / sizeof(Word),	\\
+				(total_len + sizeof(Word)) / sizeof(Word), \\
 				procname,				\\
 				""string:string/0"");			\\
 			(error_msg) = (char *)tmp;			\\
-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list