1 /* $Id: Termination.c,v 1.5 2004/12/15 11:27:03 mva Exp $ */
2 /* Provides procedures for program finalization.
3 Copyright (C) 1997, 1999, 2000, 2002 Michael van Acken
4
5 This module is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License
7 as published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
9
10 This module is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with OOC. If not, write to the Free Software Foundation,
17 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #include <stddef.h>
20 #include <stdlib.h>
21 #include <signal.h>
22 #include <sys/types.h>
23
24 #include <Termination.d>
25 #include <__config.h>
26
27 #if HAVE_UNISTD_H
28 #include <unistd.h>
29 #elif HAVE_IO_H
30 #include <io.h>
31 #endif
32
33
34 #if !HAVE_ATEXIT /* assume this is a SunOS 4, use on_exit instead */
35 extern int on_exit(void (*procp)(void),void* arg);
36 #endif
37
38 static Termination__Proc *proc_list = NULL;
39 static int proc_count = 0;
40 static int max_proc_count = 0;
41 static volatile int /*sig_atomic_t*/ noSignalHandlerInProgress = 1;
42
Termination__RegisterProc(Termination__Proc proc)43 void Termination__RegisterProc(Termination__Proc proc) {
44 int i;
45
46 if (proc_count == 0) {
47 max_proc_count = 32;
48 proc_list = RT0__NewBlock(sizeof(Termination__Proc)*max_proc_count);
49 for (i=0; i<max_proc_count; i++) {
50 proc_list[i] = (Termination__Proc)NULL;
51 }
52 } else if (proc_count == max_proc_count) {
53 static Termination__Proc *new;
54
55 max_proc_count += 32;
56 new = RT0__NewBlock(sizeof(Termination__Proc)*max_proc_count);
57 for (i=0; i<proc_count; i++) {
58 new[i] = proc_list[i];
59 }
60 for (i=proc_count; i<max_proc_count; i++) {
61 new[i] = (Termination__Proc)NULL;
62 }
63 proc_list = new;
64 }
65
66 proc_list[proc_count] = proc;
67 proc_count++;
68 }
69
Termination__UnregisterProc(Termination__Proc proc)70 void Termination__UnregisterProc(Termination__Proc proc) {
71 int i, j;
72
73 i = proc_count;
74 while (i != 0) {
75 i--;
76 if (proc_list[i] == proc) {
77 j = i+1;
78 while (j != proc_count) {
79 proc_list[j-1] = proc_list[j];
80 j++;
81 }
82 proc_count--;
83 return;
84 }
85 }
86 }
87
88
run_term_procs(void)89 static void run_term_procs (void) {
90 int i;
91 Termination__Proc ptr;
92
93 i = proc_count;
94 while (i != 0) {
95 i--;
96 ptr = proc_list[i];
97 if (ptr) {
98 proc_list[i] = (Termination__Proc)NULL;
99 (*ptr)();
100 }
101 }
102 }
103
signal_handler(int sig)104 static RETSIGTYPE signal_handler (int sig) {
105 signal(sig, SIG_DFL); /* install default handler, necessary for SunOS 4 */
106 if (noSignalHandlerInProgress) {
107 noSignalHandlerInProgress = 0;
108 run_term_procs();
109 }
110 #if HAVE_RAISE
111 raise(sig);
112 #else
113 (void)kill(getpid(), sig); /* raise signal to call default handler */
114 #endif
115 }
116
catch_signal(int sig)117 static void catch_signal (int sig) {
118 void (*func)(int);
119
120 func = signal (sig, signal_handler);
121 if (func == SIG_IGN) {
122 signal (sig, SIG_IGN);
123 }
124 }
125
OOC_Termination_init(void)126 void OOC_Termination_init(void) {
127 /* error signals */
128 catch_signal(SIGFPE);
129 catch_signal(SIGILL);
130 catch_signal(SIGSEGV);
131 catch_signal(SIGABRT);
132 #ifdef SIGBUS
133 catch_signal(SIGBUS);
134 #endif
135 #ifdef SIGIOT
136 catch_signal(SIGIOT);
137 #endif
138 #ifdef SIGSTKFLT
139 catch_signal(SIGSTKFLT);
140 #endif
141
142 /* termination signals */
143 #ifdef SIGHUP
144 catch_signal(SIGHUP);
145 #endif
146 catch_signal(SIGINT);
147 #ifdef SIGQUIT
148 catch_signal(SIGQUIT);
149 #endif
150 catch_signal(SIGTERM);
151
152 /* normal program exit */
153 #if HAVE_ATEXIT
154 (void)atexit(&run_term_procs);
155 #else
156 (void)on_exit(&run_term_procs,NULL);
157 #endif
158 }
159
OOC_Termination_destroy(void)160 void OOC_Termination_destroy(void) {
161 /* FIXME... if we ever to module unloading */
162 }
163