[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