mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-13 21:04:00 +00:00
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:
@@ -51,6 +51,7 @@ HDRS = \
|
||||
mercury_prof_mem.h \
|
||||
mercury_regorder.h \
|
||||
mercury_regs.h \
|
||||
mercury_signal.h \
|
||||
mercury_spinlock.h \
|
||||
mercury_std.h \
|
||||
mercury_stacks.h \
|
||||
@@ -99,6 +100,7 @@ CFILES = mercury_context.c \
|
||||
mercury_prof.c \
|
||||
mercury_prof_mem.c \
|
||||
mercury_regs.c \
|
||||
mercury_signal.c \
|
||||
mercury_spinlock.c \
|
||||
mercury_stack_trace.c \
|
||||
mercury_table.c \
|
||||
|
||||
@@ -186,7 +186,7 @@ init_memory(void)
|
||||
|
||||
init_memory_arena();
|
||||
init_zones();
|
||||
setup_signal();
|
||||
setup_signals();
|
||||
if (memdebug) debug_memory();
|
||||
} /* end init_memory() */
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
|
||||
#include "mercury_imp.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_SIGCONTEXT_STRUCT
|
||||
/*
|
||||
** Some versions of Linux call it struct sigcontext_struct, some call it
|
||||
@@ -43,10 +47,6 @@
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_SYS_SIGINFO
|
||||
#include <sys/siginfo.h>
|
||||
#endif
|
||||
@@ -64,6 +64,7 @@
|
||||
#endif
|
||||
|
||||
#include "mercury_imp.h"
|
||||
#include "mercury_signal.h"
|
||||
#include "mercury_trace.h"
|
||||
#include "mercury_memory_zones.h"
|
||||
#include "mercury_memory_handlers.h"
|
||||
@@ -83,6 +84,23 @@
|
||||
static void simple_sighandler(int);
|
||||
#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
|
||||
** alignment boundary. `align' must be a power of 2.
|
||||
@@ -224,56 +242,12 @@ default_handler(Word *fault_addr, MemoryZone *zone, void *context)
|
||||
}
|
||||
|
||||
void
|
||||
setup_signal(void)
|
||||
setup_signals(void)
|
||||
{
|
||||
#if defined(HAVE_SIGCONTEXT_STRUCT)
|
||||
if (signal(SIGBUS, (void(*)(int)) complex_sighandler) == SIG_ERR)
|
||||
{
|
||||
perror("cannot set SIGBUS 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
|
||||
MR_setup_signal(SIGBUS, bus_handler, TRUE,
|
||||
"Mercury runtime: cannot set SIGBUS handler");
|
||||
MR_setup_signal(SIGSEGV, segv_handler, TRUE,
|
||||
"Mercury runtime: cannot set SIGSEGV handler");
|
||||
}
|
||||
|
||||
static char *
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
** 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_prof_mem.h" /* for prof_malloc() */
|
||||
|
||||
#include "mercury_signal.h"
|
||||
#include "mercury_std.h"
|
||||
#include "mercury_timing.h"
|
||||
|
||||
@@ -204,6 +205,8 @@ checked_atexit(void (*func)(void))
|
||||
|
||||
#endif /* PROFILE_TIME or PROFILE_CALLS or PROFILE_MEMORY */
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
#ifdef PROFILE_TIME
|
||||
|
||||
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:
|
||||
** 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_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);
|
||||
}
|
||||
|
||||
|
||||
101
runtime/mercury_signal.c
Normal file
101
runtime/mercury_signal.c
Normal 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
31
runtime/mercury_signal.h
Normal 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 */
|
||||
Reference in New Issue
Block a user