blob: 006671e279cbb307f4757309dc987eeb554e7651 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijonoa771a512007-02-19 01:13:53 +00003 * Copyright (C)2003-2007 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +00004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/except.h>
20#include <pj/os.h>
21#include <pj/assert.h>
22#include <pj/log.h>
23#include <pj/errno.h>
Benny Prijono9df1d092006-07-03 01:09:20 +000024#include <pj/string.h>
Benny Prijono9033e312005-11-21 02:08:39 +000025
26static long thread_local_id = -1;
27
28#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
29 static const char *exception_id_names[PJ_MAX_EXCEPTION_ID];
30#else
31 /*
32 * Start from 1 (not 0)!!!
33 * Exception 0 is reserved for normal path of setjmp()!!!
34 */
35 static int last_exception_id = 1;
36#endif /* PJ_HAS_EXCEPTION_NAMES */
37
38
Benny Prijonod0d44f52005-11-21 16:57:02 +000039#if !defined(PJ_EXCEPTION_USE_WIN32_SEH) || PJ_EXCEPTION_USE_WIN32_SEH==0
Benny Prijono9033e312005-11-21 02:08:39 +000040PJ_DEF(void) pj_throw_exception_(int exception_id)
41{
42 struct pj_exception_state_t *handler;
43
Benny Prijonoa1e69682007-05-11 15:14:34 +000044 handler = (struct pj_exception_state_t*)
45 pj_thread_local_get(thread_local_id);
Benny Prijono9033e312005-11-21 02:08:39 +000046 if (handler == NULL) {
Benny Prijono9df1d092006-07-03 01:09:20 +000047 PJ_LOG(1,("except.c", "!!!FATAL: unhandled exception %s!\n",
48 pj_exception_id_name(exception_id)));
Benny Prijono9033e312005-11-21 02:08:39 +000049 pj_assert(handler != NULL);
50 /* This will crash the system! */
51 }
52 pj_longjmp(handler->state, exception_id);
53}
54
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000055static void exception_cleanup(void)
56{
57 if (thread_local_id != -1) {
58 pj_thread_local_free(thread_local_id);
59 thread_local_id = -1;
60 }
Benny Prijonof762ee72006-12-01 11:14:37 +000061
62#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
63 {
64 unsigned i;
65 for (i=0; i<PJ_MAX_EXCEPTION_ID; ++i)
66 exception_id_names[i] = NULL;
67 }
68#else
69 last_exception_id = 1;
70#endif
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000071}
72
Benny Prijono9033e312005-11-21 02:08:39 +000073PJ_DEF(void) pj_push_exception_handler_(struct pj_exception_state_t *rec)
74{
75 struct pj_exception_state_t *parent_handler = NULL;
76
77 if (thread_local_id == -1) {
78 pj_thread_local_alloc(&thread_local_id);
79 pj_assert(thread_local_id != -1);
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000080 pj_atexit(&exception_cleanup);
Benny Prijono9033e312005-11-21 02:08:39 +000081 }
Benny Prijonoa1e69682007-05-11 15:14:34 +000082 parent_handler = (struct pj_exception_state_t *)
83 pj_thread_local_get(thread_local_id);
Benny Prijono9033e312005-11-21 02:08:39 +000084 rec->prev = parent_handler;
85 pj_thread_local_set(thread_local_id, rec);
86}
87
88PJ_DEF(void) pj_pop_exception_handler_(void)
89{
90 struct pj_exception_state_t *handler;
91
Benny Prijonoa1e69682007-05-11 15:14:34 +000092 handler = (struct pj_exception_state_t *)
93 pj_thread_local_get(thread_local_id);
Benny Prijono9033e312005-11-21 02:08:39 +000094 pj_assert(handler != NULL);
95 pj_thread_local_set(thread_local_id, handler->prev);
96}
Benny Prijonod0d44f52005-11-21 16:57:02 +000097#endif
Benny Prijono9033e312005-11-21 02:08:39 +000098
99#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
100PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
101 pj_exception_id_t *id)
102{
103 unsigned i;
104
105 pj_enter_critical_section();
106
107 /*
108 * Start from 1 (not 0)!!!
109 * Exception 0 is reserved for normal path of setjmp()!!!
110 */
111 for (i=1; i<PJ_MAX_EXCEPTION_ID; ++i) {
112 if (exception_id_names[i] == NULL) {
113 exception_id_names[i] = name;
114 *id = i;
115 pj_leave_critical_section();
116 return PJ_SUCCESS;
117 }
118 }
119
120 pj_leave_critical_section();
121 return PJ_ETOOMANY;
122}
123
124PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
125{
126 /*
127 * Start from 1 (not 0)!!!
128 * Exception 0 is reserved for normal path of setjmp()!!!
129 */
130 PJ_ASSERT_RETURN(id>0 && id<PJ_MAX_EXCEPTION_ID, PJ_EINVAL);
131
132 pj_enter_critical_section();
133 exception_id_names[id] = NULL;
134 pj_leave_critical_section();
135
136 return PJ_SUCCESS;
137
138}
139
140PJ_DEF(const char*) pj_exception_id_name(pj_exception_id_t id)
141{
Benny Prijono9df1d092006-07-03 01:09:20 +0000142 static char unknown_name[32];
143
Benny Prijono9033e312005-11-21 02:08:39 +0000144 /*
145 * Start from 1 (not 0)!!!
146 * Exception 0 is reserved for normal path of setjmp()!!!
147 */
148 PJ_ASSERT_RETURN(id>0 && id<PJ_MAX_EXCEPTION_ID, "<Invalid ID>");
149
Benny Prijono9df1d092006-07-03 01:09:20 +0000150 if (exception_id_names[id] == NULL) {
Benny Prijonoe85bc412006-07-29 20:29:24 +0000151 pj_ansi_snprintf(unknown_name, sizeof(unknown_name),
152 "exception %d", id);
Benny Prijono9df1d092006-07-03 01:09:20 +0000153 return unknown_name;
154 }
Benny Prijono9033e312005-11-21 02:08:39 +0000155
156 return exception_id_names[id];
157}
158
159#else /* PJ_HAS_EXCEPTION_NAMES */
160PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
161 pj_exception_id_t *id)
162{
163 PJ_ASSERT_RETURN(last_exception_id < PJ_MAX_EXCEPTION_ID-1, PJ_ETOOMANY);
164
Benny Prijono11852992006-03-18 12:28:03 +0000165 *id = last_exception_id++;
Benny Prijono9033e312005-11-21 02:08:39 +0000166 return PJ_SUCCESS;
167}
168
169PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
170{
171 return PJ_SUCCESS;
172}
173
174PJ_DEF(const char*) pj_exception_id_name(pj_exception_id_t id)
175{
176 return "";
177}
178
179#endif /* PJ_HAS_EXCEPTION_NAMES */
180
181
182