for review: software errors from C code
Andrew Bromage
bromage at cs.mu.OZ.AU
Thu Mar 26 16:44:09 AEDT 1998
G'day all.
Tyson, could you review this please?
Cheers,
Andrew Bromage
Estimated hours taken: 1
Fix to allow software errors which happen in C library code to produce
a stack dump.
Note: Not every kind of fatal error in the C library is a "software
error". Only the ones which users have a hope of fixing really count
(e.g. array bounds check errors).
Also hidden away in here are two small changes:
- a fix for a problem with the user-declared array_module
which conflicts with the compiler-declared array_module.
The fix is to call the user-declared one array_moduleX.
- checked_realloc(), which is like checked_malloc() only
it calls realloc() instead of malloc().
runtime/mercury_misc.h:
runtime/mercury_misc.c:
Minor reorganisation of the way fatal errors are handled.
fatal_error() and the new function software_error() both
call clean_up_after_fatal_error() which currently does
nothing, but if any cleaning up had to be done, this is
where it should go.
Implementation of checked_realloc().
library/require.m:
Make error/1 call software_error() to ensure that any
cleanups happen.
library/array.m:
library/io.m:
library/std_util.m:
library/store.m:
Call software_error() instead of fatal_error() for the
kinds of error where a stack dump may help.
Index: library/array.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/array.m,v
retrieving revision 1.43
diff -u -r1.43 array.m
--- array.m 1998/01/30 05:59:40 1.43
+++ array.m 1998/03/26 05:13:13
@@ -287,7 +287,7 @@
Declare_entry(mercury__array__array_equal_2_0);
Declare_entry(mercury__array__array_compare_3_0);
-BEGIN_MODULE(array_module)
+BEGIN_MODULE(array_moduleX)
init_entry(mercury____Unify___array__array_1_0);
init_entry(mercury____Index___array__array_1_0);
init_entry(mercury____Compare___array__array_1_0);
@@ -311,12 +311,12 @@
/* Ensure that the initialization code for the above module gets run. */
/*
-INIT sys_init_array_module
+INIT sys_init_array_moduleX
*/
-void sys_init_array_module(void); /* suppress gcc -Wmissing-decl warning */
-void sys_init_array_module(void) {
+void sys_init_array_moduleX(void); /* suppress gcc -Wmissing-decl warning */
+void sys_init_array_moduleX(void) {
extern ModuleFunc array_module;
- array_module();
+ array_moduleX();
}
").
@@ -469,7 +469,7 @@
MR_ArrayType *array = (MR_ArrayType *)Array;
#ifndef ML_OMIT_ARRAY_BOUNDS_CHECKS
if ((Unsigned) Index >= (Unsigned) array->size) {
- fatal_error(""array__lookup: array index out of bounds"");
+ software_error(""array__lookup: array index out of bounds"");
}
#endif
Item = array->elements[Index];
@@ -478,7 +478,7 @@
MR_ArrayType *array = (MR_ArrayType *)Array;
#ifndef ML_OMIT_ARRAY_BOUNDS_CHECKS
if ((Unsigned) Index >= (Unsigned) array->size) {
- fatal_error(""array__lookup: array index out of bounds"");
+ software_error(""array__lookup: array index out of bounds"");
}
#endif
Item = array->elements[Index];
@@ -491,7 +491,7 @@
MR_ArrayType *array = (MR_ArrayType *)Array0;
#ifndef ML_OMIT_ARRAY_BOUNDS_CHECKS
if ((Unsigned) Index >= (Unsigned) array->size) {
- fatal_error(""array__set: array index out of bounds"");
+ software_error(""array__set: array index out of bounds"");
}
#endif
array->elements[Index] = Item; /* destructive update! */
@@ -565,7 +565,7 @@
old_array_size = old_array->size;
if (old_array_size == array_size) return old_array;
if (old_array_size < array_size) {
- fatal_error(""array__shrink: can't shrink to a larger size"");
+ software_error(""array__shrink: can't shrink to a larger size"");
}
array = (MR_ArrayType *) make_many(Word, array_size + 1);
Index: library/io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/io.m,v
retrieving revision 1.153
diff -u -r1.153 io.m
--- io.m 1998/03/12 19:45:38 1.153
+++ io.m 1998/03/26 05:19:49
@@ -2187,7 +2187,7 @@
}
/* XXX should work even if ungetc() fails */
if (ungetc(Character, mf->file) == EOF) {
- fatal_error(""io__putback_char: ungetc failed"");
+ software_error(""io__putback_char: ungetc failed"");
}
update_io(IO0, IO);
}").
@@ -2197,7 +2197,7 @@
MercuryFile* mf = (MercuryFile *)File;
/* XXX should work even if ungetc() fails */
if (ungetc(Character, mf->file) == EOF) {
- fatal_error(""io__putback_byte: ungetc failed"");
+ software_error(""io__putback_byte: ungetc failed"");
}
update_io(IO0, IO);
}").
@@ -2650,7 +2650,7 @@
incr_hp_atomic(tmp, (L_tmpnam + sizeof(Word)) / sizeof(Word));
if (tmpnam((char *)tmp) == NULL) {
- fatal_error(""unable to create temporary filename"");
+ software_error(""unable to create temporary filename"");
}
FileName = (char *)tmp;
update_io(IO0, IO);
@@ -2688,7 +2688,7 @@
tmp = tempnam(Dir, Prefix);
if (tmp == NULL) {
- fatal_error(""unable to create temporary filename"");
+ software_error(""unable to create temporary filename"");
}
incr_hp_atomic(LVALUE_CAST(Word *,FileName),
(strlen(tmp) + sizeof(Word)) / sizeof(Word));
@@ -2727,7 +2727,7 @@
} while ((err != -1 || errno != ENOENT)
&& num_tries < MAX_TEMPNAME_TRIES);
if (err != -1 || errno != ENOENT) {
- fatal_error(""unable to create temporary filename"");
+ software_error(""unable to create temporary filename"");
}
update_io(IO0, IO);
#endif
Index: library/require.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/require.m,v
retrieving revision 1.18
diff -u -r1.18 require.m
--- require.m 1998/03/11 05:57:41 1.18
+++ require.m 1998/03/26 05:14:24
@@ -56,10 +56,7 @@
:- pragma no_inline(error/1).
:- pragma c_code(error(Message::in), "
- fflush(stdout);
- fprintf(stderr, ""Software error: %s\\n"", Message);
- MR_dump_stack(MR_succip, MR_sp);
- exit(1);
+ software_error(Message);
#ifndef USE_GCC_NONLOCAL_GOTOS
return 0; /* suppress some dumb warnings */
#endif
Index: library/std_util.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/std_util.m,v
retrieving revision 1.115
diff -u -r1.115 std_util.m
--- std_util.m 1998/01/30 02:15:04 1.115
+++ std_util.m 1998/03/26 05:13:42
@@ -552,7 +552,7 @@
#ifndef CONSERVATIVE_GC
#ifndef USE_TYPE_LAYOUT
- fatal_error(""builtin_aggregate/4 not supported with this grade ""
+ software_error(""builtin_aggregate/4 not supported with this grade ""
""on this system.\n""
""Try using a `.gc' (conservative gc) grade.\n"");
#endif
@@ -2772,7 +2772,7 @@
** that allows this.)
*/
if (info.non_canonical_type) {
- fatal_error(""called argument/2 for a type with a ""
+ software_error(""called argument/2 for a type with a ""
""user-defined equality predicate"");
}
@@ -2829,7 +2829,7 @@
** that allows this.)
*/
if (info.non_canonical_type) {
- fatal_error(""called functor/2 for a type with a ""
+ software_error(""called functor/2 for a type with a ""
""user-defined equality predicate"");
}
@@ -2947,7 +2947,7 @@
** that allows this.)
*/
if (info.non_canonical_type) {
- fatal_error(""called deconstruct/4 for a type with a ""
+ software_error(""called deconstruct/4 for a type with a ""
""user-defined equality predicate"");
}
Index: library/store.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/store.m,v
retrieving revision 1.12
diff -u -r1.12 store.m
--- store.m 1998/01/23 12:33:37 1.12
+++ store.m 1998/03/26 05:13:43
@@ -323,13 +323,13 @@
if (!ML_arg(TypeInfo_for_T, (Word *) Ref, ArgNum,
&arg_type_info, &arg_ref))
{
- fatal_error(""store__arg_ref: argument number out of range"");
+ software_error(""store__arg_ref: argument number out of range"");
}
if (ML_compare_type_info(arg_type_info, TypeInfo_for_ArgT) !=
COMPARE_EQUAL)
{
- fatal_error(""store__arg_ref: argument has wrong type"");
+ software_error(""store__arg_ref: argument has wrong type"");
}
restore_transient_registers();
@@ -349,13 +349,13 @@
if (!ML_arg(TypeInfo_for_T, (Word *) &Val, ArgNum,
&arg_type_info, &arg_ref))
{
- fatal_error(""store__new_arg_ref: argument number out of range"");
+ software_error(""store__new_arg_ref: argument number out of range"");
}
if (ML_compare_type_info(arg_type_info, TypeInfo_for_ArgT) !=
COMPARE_EQUAL)
{
- fatal_error(""store__new_arg_ref: argument has wrong type"");
+ software_error(""store__new_arg_ref: argument has wrong type"");
}
restore_transient_registers();
Index: runtime/mercury_misc.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_misc.c,v
retrieving revision 1.4
diff -u -r1.4 mercury_misc.c
--- mercury_misc.c 1998/03/16 12:23:33 1.4
+++ mercury_misc.c 1998/03/26 05:10:11
@@ -462,25 +462,55 @@
return p;
}
-/* XXX will need to modify this to kill other processes if PARALLEL
- * (and cleanup resources, etc....)
- */
+static void
+clean_up_after_fatal_error(void)
+{
+ /* XXX will need to modify this to kill other processes if PARALLEL
+ * (and cleanup resources, etc....)
+ */
+}
+
void
fatal_error(const char *message) {
+ fflush(stdout);
fprintf(stderr, "Mercury runtime: %s\n", message);
+ clean_up_after_fatal_error();
+ exit(1);
+}
+
+void
+software_error(const char *message) {
+ fflush(stdout);
+ fprintf(stderr, "Software error: %s\n", message);
+ MR_dump_stack(MR_succip, MR_sp);
+ clean_up_after_fatal_error();
exit(1);
}
- /* Note: checked_malloc()ed structures */
- /* never contain pointers into GCed */
- /* memory, so we don't need to */
- /* GC_malloc() them. (cf. newmem()) */
+ /* Note: checked_malloc()ed and */
+ /* checked_realloc()ed structures */
+ /* never contain pointers into GCed */
+ /* memory, so we don't need to */
+ /* GC_malloc() them. (cf. newmem()) */
void *
checked_malloc(size_t n)
{
reg void *p;
p = malloc(n);
+ if (p == NULL && n != 0) {
+ fatal_error("ran out of memory");
+ }
+
+ return p;
+}
+
+void *
+checked_realloc(void *old, size_t n)
+{
+ reg void *p;
+
+ p = realloc(old, n);
if (p == NULL && n != 0) {
fatal_error("ran out of memory");
}
Index: runtime/mercury_misc.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_misc.h,v
retrieving revision 1.4
diff -u -r1.4 mercury_misc.h
--- mercury_misc.h 1998/03/16 12:23:34 1.4
+++ mercury_misc.h 1998/03/26 05:10:34
@@ -62,11 +62,14 @@
#define NO_RETURN
#endif
extern void fatal_error(const char *msg) NO_RETURN;
+extern void software_error(const char *msg) NO_RETURN;
/*
-** XXX checked_malloc() should be moved to mercury_memory.h or mercury_heap.h
+** XXX checked_malloc() and checked_realloc() should be moved to
+** mercury_memory.h or mercury_heap.h
*/
#include <stddef.h> /* for size_t */
void *checked_malloc(size_t n);
+void *checked_realloc(void *old, size_t n);
#endif /* not MERCURY_MISC_H */
More information about the developers
mailing list