Statistics
| Branch: | Revision:

root / prex-0.9.0 / usr / lib / posix / signal / __exception.c @ 03e9c04a

History | View | Annotate | Download (4.18 KB)

1
/*
2
 * Copyright (c) 2005-2009, Kohsuke Ohtani
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the author nor the names of any co-contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29

    
30
#include <sys/prex.h>
31
#include <sys/signal.h>
32

    
33
#include <unistd.h>
34
#include <signal.h>
35
#include <stdlib.h>
36

    
37
void __exception_init(void);
38
void __exception_exit(int *);
39

    
40
static int __sig_exit;
41

    
42
struct sigaction __sig_act[NSIG];
43
sigset_t __sig_mask;
44
sigset_t __sig_pending;
45

    
46
#ifdef _REENTRANT
47
volatile mutex_t __sig_lock;
48
#endif
49

    
50
/*
51
 * Process all pending and unmasked signal
52
 *
53
 * return 0 if at least one pending signal was processed.
54
 * return -1 if no signal was processed.
55
 */
56
int
57
__sig_flush(void)
58
{
59
        int sig;
60
        sigset_t active, org_mask;
61
        struct sigaction action;
62
        struct siginfo si;
63
        int rc = -1;
64

    
65
        sig = 1;
66
        for (;;) {
67
                SIGNAL_LOCK();
68
                active = __sig_pending & ~__sig_mask;
69
                action = __sig_act[sig];
70
                SIGNAL_UNLOCK();
71

    
72
                if (active == 0)
73
                        break;
74
                if (active & sigmask(sig)) {
75

    
76
                        SIGNAL_LOCK();
77
                        org_mask = __sig_mask;
78
                        __sig_mask |= action.sa_mask;
79
                        SIGNAL_UNLOCK();
80

    
81
                        if (action.sa_handler == SIG_DFL) {
82
                                /* Default */
83
                                switch (sig) {
84
                                case SIGCHLD:
85
                                case SIGTSTP:
86
                                        /* XXX: */
87
                                        break;
88
                                default:
89
                                        SIGNAL_LOCK();
90
                                        __sig_pending &= ~sigmask(sig);
91
                                        __sig_mask = org_mask;
92
                                        __sig_exit = sig;
93
                                        SIGNAL_UNLOCK();
94
                                        exit(0);
95
                                }
96
                        } else if (action.sa_handler != SIG_IGN) {
97
                                /* User defined */
98
                                if (action.sa_flags & SA_SIGINFO) {
99
                                        si.si_signo = sig;
100
                                        si.si_code = 0;
101
                                        si.si_value.sival_int = 0;
102
                                        action.sa_sigaction(sig, &si, NULL);
103
                                } else {
104
                                        action.sa_handler(sig);
105
                                }
106
                        }
107
                        SIGNAL_LOCK();
108
                        __sig_pending &= ~sigmask(sig);
109
                        __sig_mask = org_mask;
110
                        SIGNAL_UNLOCK();
111

    
112
                        switch (sig) {
113
                        case SIGILL:
114
                        case SIGTRAP:
115
                        case SIGFPE:
116
                        case SIGSEGV:
117
                                for (;;);        /* exception from kernel */
118
                                break;
119
                        }
120
                        if (action.sa_handler != SIG_IGN)
121
                                rc = 0;        /* Signal is processed */
122
                }
123

    
124
                if (++sig >= NSIG)
125
                        sig = 1;
126
        }
127
        return rc;
128
}
129

    
130
/*
131
 * Exception handler for signal emulation
132
 */
133
static void
134
__exception_handler(int excpt)
135
{
136

    
137
        if (excpt > 0 && excpt <= NSIG) {
138

    
139
                SIGNAL_LOCK();
140

    
141
                if (__sig_act[excpt].sa_handler != SIG_IGN)
142
                        __sig_pending |= sigmask(excpt);
143

    
144
                SIGNAL_UNLOCK();
145
        }
146
        __sig_flush();
147
        exception_return();
148
}
149

    
150
/*
151
 * Initialize exception
152
 */
153
void
154
__exception_init(void)
155
{
156
        int i;
157

    
158
#ifdef _REENTRANT
159
        mutex_init(&__sig_lock);
160
#endif
161
        exception_setup(EXC_DFL);
162

    
163
        __sig_mask = 0;
164
        __sig_pending = 0;
165
        __sig_exit = 0;
166

    
167
        for (i = 0; i < NSIG; i++) {
168
                __sig_act[i].sa_flags = 0;
169
                __sig_act[i].sa_handler = SIG_DFL;
170
        }
171

    
172
        /* Install exception handler */
173
        exception_setup(__exception_handler);
174
}
175

    
176
/*
177
 * Clean up
178
 */
179
void
180
__exception_exit(int *signo)
181
{
182

    
183
#ifdef _REENTRANT
184
        mutex_destroy(&__sig_lock);
185
#endif
186
        exception_setup(EXC_DFL);
187

    
188
        *signo = __sig_exit;
189
        __sig_exit = 0;
190
        __sig_pending = 0;
191
}