blob: 66aa56e67813a7d66c20d0f87fd7b11b1aea6b7c [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pj/except.h>
21#include <pj/os.h>
22#include <pj/assert.h>
23#include <pj/log.h>
24#include <pj/errno.h>
Benny Prijono9df1d092006-07-03 01:09:20 +000025#include <pj/string.h>
Benny Prijono9033e312005-11-21 02:08:39 +000026
27static long thread_local_id = -1;
28
29#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
30 static const char *exception_id_names[PJ_MAX_EXCEPTION_ID];
31#else
32 /*
33 * Start from 1 (not 0)!!!
34 * Exception 0 is reserved for normal path of setjmp()!!!
35 */
36 static int last_exception_id = 1;
37#endif /* PJ_HAS_EXCEPTION_NAMES */
38
39
Benny Prijonod0d44f52005-11-21 16:57:02 +000040#if !defined(PJ_EXCEPTION_USE_WIN32_SEH) || PJ_EXCEPTION_USE_WIN32_SEH==0
Benny Prijono9033e312005-11-21 02:08:39 +000041PJ_DEF(void) pj_throw_exception_(int exception_id)
42{
43 struct pj_exception_state_t *handler;
44
Benny Prijonoa1e69682007-05-11 15:14:34 +000045 handler = (struct pj_exception_state_t*)
46 pj_thread_local_get(thread_local_id);
Benny Prijono9033e312005-11-21 02:08:39 +000047 if (handler == NULL) {
Benny Prijono9df1d092006-07-03 01:09:20 +000048 PJ_LOG(1,("except.c", "!!!FATAL: unhandled exception %s!\n",
49 pj_exception_id_name(exception_id)));
Benny Prijono9033e312005-11-21 02:08:39 +000050 pj_assert(handler != NULL);
51 /* This will crash the system! */
52 }
53 pj_longjmp(handler->state, exception_id);
54}
55
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000056static void exception_cleanup(void)
57{
58 if (thread_local_id != -1) {
59 pj_thread_local_free(thread_local_id);
60 thread_local_id = -1;
61 }
Benny Prijonof762ee72006-12-01 11:14:37 +000062
63#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
64 {
65 unsigned i;
66 for (i=0; i<PJ_MAX_EXCEPTION_ID; ++i)
67 exception_id_names[i] = NULL;
68 }
69#else
70 last_exception_id = 1;
71#endif
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000072}
73
Benny Prijono9033e312005-11-21 02:08:39 +000074PJ_DEF(void) pj_push_exception_handler_(struct pj_exception_state_t *rec)
75{
76 struct pj_exception_state_t *parent_handler = NULL;
77
78 if (thread_local_id == -1) {
79 pj_thread_local_alloc(&thread_local_id);
80 pj_assert(thread_local_id != -1);
Benny Prijonoaf1bb1e2006-11-21 12:39:31 +000081 pj_atexit(&exception_cleanup);
Benny Prijono9033e312005-11-21 02:08:39 +000082 }
Benny Prijonoa1e69682007-05-11 15:14:34 +000083 parent_handler = (struct pj_exception_state_t *)
84 pj_thread_local_get(thread_local_id);
Benny Prijono9033e312005-11-21 02:08:39 +000085 rec->prev = parent_handler;
86 pj_thread_local_set(thread_local_id, rec);
87}
88
89PJ_DEF(void) pj_pop_exception_handler_(void)
90{
91 struct pj_exception_state_t *handler;
92
Benny Prijonoa1e69682007-05-11 15:14:34 +000093 handler = (struct pj_exception_state_t *)
94 pj_thread_local_get(thread_local_id);
Benny Prijono9033e312005-11-21 02:08:39 +000095 pj_assert(handler != NULL);
96 pj_thread_local_set(thread_local_id, handler->prev);
97}
Benny Prijonod0d44f52005-11-21 16:57:02 +000098#endif
Benny Prijono9033e312005-11-21 02:08:39 +000099
100#if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
101PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
102 pj_exception_id_t *id)
103{
104 unsigned i;
105
106 pj_enter_critical_section();
107
108 /*
109 * Start from 1 (not 0)!!!
110 * Exception 0 is reserved for normal path of setjmp()!!!
111 */
112 for (i=1; i<PJ_MAX_EXCEPTION_ID; ++i) {
113 if (exception_id_names[i] == NULL) {
114 exception_id_names[i] = name;
115 *id = i;
116 pj_leave_critical_section();
117 return PJ_SUCCESS;
118 }
119 }
120
121 pj_leave_critical_section();
122 return PJ_ETOOMANY;
123}
124
125PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
126{
127 /*
128 * Start from 1 (not 0)!!!
129 * Exception 0 is reserved for normal path of setjmp()!!!
130 */
131 PJ_ASSERT_RETURN(id>0 && id<PJ_MAX_EXCEPTION_ID, PJ_EINVAL);
132
133 pj_enter_critical_section();
134 exception_id_names[id] = NULL;
135 pj_leave_critical_section();
136
137 return PJ_SUCCESS;
138
139}
140
141PJ_DEF(const char*) pj_exception_id_name(pj_exception_id_t id)
142{
Benny Prijono9df1d092006-07-03 01:09:20 +0000143 static char unknown_name[32];
144
Benny Prijono9033e312005-11-21 02:08:39 +0000145 /*
146 * Start from 1 (not 0)!!!
147 * Exception 0 is reserved for normal path of setjmp()!!!
148 */
149 PJ_ASSERT_RETURN(id>0 && id<PJ_MAX_EXCEPTION_ID, "<Invalid ID>");
150
Benny Prijono9df1d092006-07-03 01:09:20 +0000151 if (exception_id_names[id] == NULL) {
Benny Prijonoe85bc412006-07-29 20:29:24 +0000152 pj_ansi_snprintf(unknown_name, sizeof(unknown_name),
153 "exception %d", id);
Benny Prijono9df1d092006-07-03 01:09:20 +0000154 return unknown_name;
155 }
Benny Prijono9033e312005-11-21 02:08:39 +0000156
157 return exception_id_names[id];
158}
159
160#else /* PJ_HAS_EXCEPTION_NAMES */
161PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
162 pj_exception_id_t *id)
163{
164 PJ_ASSERT_RETURN(last_exception_id < PJ_MAX_EXCEPTION_ID-1, PJ_ETOOMANY);
165
Benny Prijono11852992006-03-18 12:28:03 +0000166 *id = last_exception_id++;
Benny Prijono9033e312005-11-21 02:08:39 +0000167 return PJ_SUCCESS;
168}
169
170PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
171{
172 return PJ_SUCCESS;
173}
174
175PJ_DEF(const char*) pj_exception_id_name(pj_exception_id_t id)
176{
177 return "";
178}
179
180#endif /* PJ_HAS_EXCEPTION_NAMES */
181
182
183