More cleanup of the memory management code.

Estimated hours taken: 5

More cleanup of the memory management code.
This time we clean up the signal handler setup code.

runtime/Mmakefile:
	Add new files.

runtime/mercury_memory.c:
	Rename setup_signal() to setup_signals().

runtime/mercury_memory_handlers.c:
runtime/mercury_memory_handlers.h:
	Clean up signal handling.
	Use MR_setup_signal to setup signal handlers.
	Define bus_handler and segv_handler signal handlers, the
	old signal handlers are just one or the other (or both).

runtime/mercury_prof.c:
	Use MR_setup_signal to setup signal handler.

runtime/mercury_signal.c:
runtime/mercury_signal.h:
	New files -- a standard interface for setting up signal
	handlers (a porting base, if you like).
This commit is contained in:
Tyson Dowd
1998-05-14 06:35:16 +00:00
parent 564d358da3
commit cd3914c609
7 changed files with 170 additions and 98 deletions

View File

@@ -51,6 +51,7 @@ HDRS = \
mercury_prof_mem.h \ mercury_prof_mem.h \
mercury_regorder.h \ mercury_regorder.h \
mercury_regs.h \ mercury_regs.h \
mercury_signal.h \
mercury_spinlock.h \ mercury_spinlock.h \
mercury_std.h \ mercury_std.h \
mercury_stacks.h \ mercury_stacks.h \
@@ -99,6 +100,7 @@ CFILES = mercury_context.c \
mercury_prof.c \ mercury_prof.c \
mercury_prof_mem.c \ mercury_prof_mem.c \
mercury_regs.c \ mercury_regs.c \
mercury_signal.c \
mercury_spinlock.c \ mercury_spinlock.c \
mercury_stack_trace.c \ mercury_stack_trace.c \
mercury_table.c \ mercury_table.c \

View File

@@ -186,7 +186,7 @@ init_memory(void)
init_memory_arena(); init_memory_arena();
init_zones(); init_zones();
setup_signal(); setup_signals();
if (memdebug) debug_memory(); if (memdebug) debug_memory();
} /* end init_memory() */ } /* end init_memory() */

View File

@@ -15,6 +15,10 @@
#include "mercury_imp.h" #include "mercury_imp.h"
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SIGCONTEXT_STRUCT #ifdef HAVE_SIGCONTEXT_STRUCT
/* /*
** Some versions of Linux call it struct sigcontext_struct, some call it ** Some versions of Linux call it struct sigcontext_struct, some call it
@@ -43,10 +47,6 @@
#include <signal.h> #include <signal.h>
#endif #endif
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_SIGINFO #ifdef HAVE_SYS_SIGINFO
#include <sys/siginfo.h> #include <sys/siginfo.h>
#endif #endif
@@ -64,6 +64,7 @@
#endif #endif
#include "mercury_imp.h" #include "mercury_imp.h"
#include "mercury_signal.h"
#include "mercury_trace.h" #include "mercury_trace.h"
#include "mercury_memory_zones.h" #include "mercury_memory_zones.h"
#include "mercury_memory_handlers.h" #include "mercury_memory_handlers.h"
@@ -83,6 +84,23 @@
static void simple_sighandler(int); static void simple_sighandler(int);
#endif #endif
#ifdef HAVE_SIGINFO
#if defined(HAVE_SIGCONTEXT_STRUCT)
#define bus_handler complex_sighandler
#define segv_handler complex_sighandler
#elif defined(HAVE_SIGINFO_T)
#define bus_handler complex_bushandler
#define segv_handler complex_segvhandler
#else
#error "HAVE_SIGINFO defined but don't know how to get it"
#endif
#else
#define bus_handler simple_sighandler
#define segv_handler simple_sighandler
#endif
/* /*
** round_up(amount, align) returns `amount' rounded up to the nearest ** round_up(amount, align) returns `amount' rounded up to the nearest
** alignment boundary. `align' must be a power of 2. ** alignment boundary. `align' must be a power of 2.
@@ -224,56 +242,12 @@ default_handler(Word *fault_addr, MemoryZone *zone, void *context)
} }
void void
setup_signal(void) setup_signals(void)
{ {
#if defined(HAVE_SIGCONTEXT_STRUCT) MR_setup_signal(SIGBUS, bus_handler, TRUE,
if (signal(SIGBUS, (void(*)(int)) complex_sighandler) == SIG_ERR) "Mercury runtime: cannot set SIGBUS handler");
{ MR_setup_signal(SIGSEGV, segv_handler, TRUE,
perror("cannot set SIGBUS handler"); "Mercury runtime: cannot set SIGSEGV handler");
exit(1);
}
if (signal(SIGSEGV, (void(*)(int)) complex_sighandler) == SIG_ERR)
{
perror("cannot set SIGSEGV handler");
exit(1);
}
#elif defined(HAVE_SIGINFO_T)
struct sigaction act;
act.sa_flags = SA_SIGINFO | SA_RESTART;
if (sigemptyset(&act.sa_mask) != 0) {
perror("Mercury runtime: cannot set clear signal mask");
exit(1);
}
act.SIGACTION_FIELD = complex_bushandler;
if (sigaction(SIGBUS, &act, NULL) != 0) {
perror("Mercury runtime: cannot set SIGBUS handler");
exit(1);
}
act.SIGACTION_FIELD = complex_segvhandler;
if (sigaction(SIGSEGV, &act, NULL) != 0) {
perror("Mercury runtime: cannot set SIGSEGV handler");
exit(1);
}
#else /* not HAVE_SIGINFO_T && not HAVE_SIGCONTEXT_STRUCT */
if (signal(SIGBUS, simple_sighandler) == SIG_ERR) {
perror("cannot set SIGBUS handler");
exit(1);
}
if (signal(SIGSEGV, simple_sighandler) == SIG_ERR) {
perror("cannot set SIGSEGV handler");
exit(1);
}
#endif
} }
static char * static char *

View File

@@ -31,10 +31,10 @@ ZoneHandler null_handler;
/* /*
** **
** setup_signal() will setup the default signal handlers. ** setup_signals() will setup the default signal handlers.
** **
*/ */
void setup_signal(void); void setup_signals(void);
#endif /* not MERCURY_MEMORY_HANDLERS_H */ #endif /* not MERCURY_MEMORY_HANDLERS_H */

View File

@@ -1,5 +1,5 @@
/* /*
** Copyright (C) 1995-1997 The University of Melbourne. ** Copyright (C) 1995-1998 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General ** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution. ** Public License - see the file COPYING.LIB in the Mercury distribution.
*/ */
@@ -21,6 +21,7 @@
#include "mercury_heap_profile.h" /* for MR_prof_output_mem_tables() */ #include "mercury_heap_profile.h" /* for MR_prof_output_mem_tables() */
#include "mercury_prof_mem.h" /* for prof_malloc() */ #include "mercury_prof_mem.h" /* for prof_malloc() */
#include "mercury_signal.h"
#include "mercury_std.h" #include "mercury_std.h"
#include "mercury_timing.h" #include "mercury_timing.h"
@@ -204,6 +205,8 @@ checked_atexit(void (*func)(void))
#endif /* PROFILE_TIME or PROFILE_CALLS or PROFILE_MEMORY */ #endif /* PROFILE_TIME or PROFILE_CALLS or PROFILE_MEMORY */
/* ======================================================================== */
#ifdef PROFILE_TIME #ifdef PROFILE_TIME
static void static void
@@ -216,46 +219,6 @@ checked_setitimer(int which, struct itimerval *value)
} }
} }
static void
checked_signal(int sig, void (*handler)(int))
{
/*
** We really need sigaction and SA_RESTART, otherwise profiling signals
** might interrupt I/O, causing a profiled program to get I/O errors.
** But if we haven't got it, I guess we just have to punt...
*/
#ifndef SA_RESTART
#define SA_RESTART 0
#endif
#ifdef HAVE_SIGACTION
struct sigaction act;
act.sa_flags = SA_RESTART;
if (sigemptyset(&act.sa_mask) != 0) {
perror("Mercury runtime: cannot set clear signal mask");
exit(1);
}
act.sa_handler = handler;
#endif /* HAVE_SIGACTION */
errno = 0;
#ifdef HAVE_SIGACTION
if (sigaction(sig, &act, NULL) != 0)
#else
if (signal(sig, handler) == SIG_ERR)
#endif /* HAVE_SIGACTION */
{
perror("Mercury runtime: cannot install signal handler");
exit(1);
}
}
#endif /* PROFILE_TIME */
/* ======================================================================== */
#ifdef PROFILE_TIME
/* /*
** prof_turn_on_time_profiling: ** prof_turn_on_time_profiling:
** Sets up the profiling timer and starts it up. ** Sets up the profiling timer and starts it up.
@@ -282,7 +245,8 @@ MR_prof_turn_on_time_profiling(void)
itime.it_interval.tv_sec = 0; itime.it_interval.tv_sec = 0;
itime.it_interval.tv_usec = prof_sig_interval_in_usecs; itime.it_interval.tv_usec = prof_sig_interval_in_usecs;
checked_signal(MR_itimer_sig, prof_time_profile); MR_setup_signal(MR_itimer_sig, prof_time_profile,
"Mercury runtime: cannot install signal handler");
checked_setitimer(MR_itimer_type, &itime); checked_setitimer(MR_itimer_type, &itime);
} }

101
runtime/mercury_signal.c Normal file
View File

@@ -0,0 +1,101 @@
/*
** Copyright (C) 1998 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
/*
** This module defines functions for setting up signal handlers.
*/
/*---------------------------------------------------------------------------*/
#include "mercury_imp.h"
#ifdef HAVE_SIGCONTEXT_STRUCT
/*
** Some versions of Linux call it struct sigcontext_struct, some call it
** struct sigcontext. The following #define eliminates the differences.
*/
#define sigcontext_struct sigcontext /* must be before #include <signal.h> */
/*
** On some systems (e.g. most versions of Linux) we need to #define
** __KERNEL__ to get sigcontext_struct from <signal.h>.
** This stuff must come before anything else that might include <signal.h>,
** otherwise the #define __KERNEL__ may not work.
*/
#define __KERNEL__
#include <signal.h> /* must come third */
#undef __KERNEL__
/*
** Some versions of Linux define it in <signal.h>, others define it in
** <asm/sigcontext.h>. We try both.
*/
#ifdef HAVE_ASM_SIGCONTEXT
#include <asm/sigcontext.h>
#endif
#else
#include <signal.h>
#endif
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_SIGINFO
#include <sys/siginfo.h>
#endif
#ifdef HAVE_MPROTECT
#include <sys/mman.h>
#endif
#ifdef HAVE_UCONTEXT
#include <ucontext.h>
#endif
#ifdef HAVE_SYS_UCONTEXT
#include <sys/ucontext.h>
#endif
#include "mercury_imp.h"
#include "mercury_signal.h"
/*---------------------------------------------------------------------------*/
void
MR_setup_signal(int sig, void *handler, int need_info,
const char *error_message)
{
#if defined(HAVE_SIGINFO_T)
struct sigaction act;
if (need_info) {
act.sa_flags = SA_SIGINFO | SA_RESTART;
} else {
act.sa_flags = SA_RESTART;
}
if (sigemptyset(&act.sa_mask) != 0) {
perror("Mercury runtime: cannot set clear signal mask");
exit(1);
}
errno = 0;
act.SIGACTION_FIELD = handler;
if (sigaction(sig, &act, NULL) != 0) {
perror(error_message);
exit(1);
}
#else /* not HAVE_SIGINFO_T */
if (signal(sig, handler) == SIG_ERR) {
perror(error_message);
exit(1);
}
#endif /* not HAVE_SIGINFO_T */
}

31
runtime/mercury_signal.h Normal file
View File

@@ -0,0 +1,31 @@
/*
** Copyright (C) 1998 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
/*
** mercury_signal.h - functions for setting up signal handlers.
**
** This defines a generic signal handler setup mechanism.
*/
#ifndef MERCURY_SIGNAL_H
#define MERCURY_SIGNAL_H
/*
** MR_setup_signal sets a signal handler (handler) to handle
** signals of the given signal type (sig).
** If the handler cannot be setup, it aborts with the given
** error message.
**
** If the signal handler requires siginfo to be provided (e.g.
** it needs access to stored registers), need_info must be
** TRUE. Note that on some platforms, signal information is
** provided regardless of the value of need_info.
*/
extern void MR_setup_signal(int sig, void *handler, int need_info,
const char * error_message);
#endif /* not MERCURY_SIGNAL_H */