From cd3914c609b9937a1f7189a956e40d53b0180be9 Mon Sep 17 00:00:00 2001 From: Tyson Dowd Date: Thu, 14 May 1998 06:35:16 +0000 Subject: [PATCH] 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). --- runtime/Mmakefile | 2 + runtime/mercury_memory.c | 2 +- runtime/mercury_memory_handlers.c | 80 ++++++++--------------- runtime/mercury_memory_handlers.h | 4 +- runtime/mercury_prof.c | 48 ++------------ runtime/mercury_signal.c | 101 ++++++++++++++++++++++++++++++ runtime/mercury_signal.h | 31 +++++++++ 7 files changed, 170 insertions(+), 98 deletions(-) create mode 100644 runtime/mercury_signal.c create mode 100644 runtime/mercury_signal.h diff --git a/runtime/Mmakefile b/runtime/Mmakefile index e24bed89f..2b69202c7 100644 --- a/runtime/Mmakefile +++ b/runtime/Mmakefile @@ -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 \ diff --git a/runtime/mercury_memory.c b/runtime/mercury_memory.c index c703207d0..80c6bd59e 100644 --- a/runtime/mercury_memory.c +++ b/runtime/mercury_memory.c @@ -186,7 +186,7 @@ init_memory(void) init_memory_arena(); init_zones(); - setup_signal(); + setup_signals(); if (memdebug) debug_memory(); } /* end init_memory() */ diff --git a/runtime/mercury_memory_handlers.c b/runtime/mercury_memory_handlers.c index cf7064735..c699e0f94 100644 --- a/runtime/mercury_memory_handlers.c +++ b/runtime/mercury_memory_handlers.c @@ -15,6 +15,10 @@ #include "mercury_imp.h" +#include +#include +#include + #ifdef HAVE_SIGCONTEXT_STRUCT /* ** Some versions of Linux call it struct sigcontext_struct, some call it @@ -43,10 +47,6 @@ #include #endif -#include -#include -#include - #ifdef HAVE_SYS_SIGINFO #include #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 * diff --git a/runtime/mercury_memory_handlers.h b/runtime/mercury_memory_handlers.h index 9a51efd33..dfb239f06 100644 --- a/runtime/mercury_memory_handlers.h +++ b/runtime/mercury_memory_handlers.h @@ -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 */ diff --git a/runtime/mercury_prof.c b/runtime/mercury_prof.c index bfefe9051..80665c652 100644 --- a/runtime/mercury_prof.c +++ b/runtime/mercury_prof.c @@ -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); } diff --git a/runtime/mercury_signal.c b/runtime/mercury_signal.c new file mode 100644 index 000000000..6cf650326 --- /dev/null +++ b/runtime/mercury_signal.c @@ -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 */ + + /* + ** On some systems (e.g. most versions of Linux) we need to #define + ** __KERNEL__ to get sigcontext_struct from . + ** This stuff must come before anything else that might include , + ** otherwise the #define __KERNEL__ may not work. + */ + #define __KERNEL__ + #include /* must come third */ + #undef __KERNEL__ + + /* + ** Some versions of Linux define it in , others define it in + ** . We try both. + */ + #ifdef HAVE_ASM_SIGCONTEXT + #include + #endif +#else + #include +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_SIGINFO + #include +#endif + +#ifdef HAVE_MPROTECT + #include +#endif + +#ifdef HAVE_UCONTEXT + #include +#endif + +#ifdef HAVE_SYS_UCONTEXT + #include +#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 */ +} + diff --git a/runtime/mercury_signal.h b/runtime/mercury_signal.h new file mode 100644 index 000000000..12c7f663e --- /dev/null +++ b/runtime/mercury_signal.h @@ -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 */