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_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 \
|
||||||
|
|||||||
@@ -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() */
|
||||||
|
|
||||||
|
|||||||
@@ -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 *
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
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