Line data Source code
1 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 : /*
3 : * lt-error.c
4 : * Copyright (C) 2011-2012 Akira TAGOH
5 : *
6 : * Authors:
7 : * Akira TAGOH <akira@tagoh.org>
8 : *
9 : * You may distribute under the terms of either the GNU
10 : * Lesser General Public License or the Mozilla Public
11 : * License, as specified in the README file.
12 : */
13 : #ifdef HAVE_CONFIG_H
14 : #include "config.h"
15 : #endif
16 :
17 : #ifndef _WIN32
18 : #include <execinfo.h>
19 : #endif
20 : #include <stdlib.h>
21 : #include "lt-list.h"
22 : #include "lt-mem.h"
23 : #include "lt-messages.h"
24 : #include "lt-utils.h"
25 : #include "lt-error.h"
26 :
27 : struct _lt_error_t {
28 : lt_mem_t parent;
29 : lt_list_t *data;
30 : };
31 : typedef struct _lt_error_data_t {
32 : lt_mem_t parent;
33 : lt_error_type_t type;
34 : char *message;
35 : char **traces;
36 : size_t stack_size;
37 : } lt_error_data_t;
38 :
39 : /**
40 : * SECTION:lt-error
41 : * @Short_Description: Error handling
42 : * @Title: Error
43 : *
44 : * This section describes the error handling in this library.
45 : */
46 : /*< private >*/
47 : lt_error_t *
48 14 : lt_error_new(void)
49 : {
50 14 : return lt_mem_alloc_object(sizeof (lt_error_t));
51 : }
52 :
53 : /*< public >*/
54 :
55 : /**
56 : * lt_error_ref:
57 : * @error: a #lt_error_t
58 : *
59 : * Inscreases the reference count of @error.
60 : *
61 : * Returns: (transfer none): the same @error object.
62 : */
63 : lt_error_t *
64 14 : lt_error_ref(lt_error_t *error)
65 : {
66 14 : lt_return_val_if_fail (error != NULL, NULL);
67 :
68 14 : return lt_mem_ref(&error->parent);
69 : }
70 :
71 : /**
72 : * lt_error_unref:
73 : * @error: a #lt_error_t
74 : *
75 : * Decreases the reference count of @error. when its reference count
76 : * drops to 0, the object is finalized (i.e. its memory is freed).
77 : */
78 : void
79 28 : lt_error_unref(lt_error_t *error)
80 : {
81 28 : if (error)
82 28 : lt_mem_unref(&error->parent);
83 28 : }
84 :
85 : /**
86 : * lt_error_set:
87 : * @error: a return location for a #lt_error_t
88 : * @type: a #lt_error_type_t
89 : * @message: the string format to output the error messages
90 : * @...: the parameters to insert into the format string
91 : *
92 : * Sets the error into @error according to the given parameters.
93 : *
94 : * Returns: an instance of #lt_error_t
95 : */
96 : lt_error_t *
97 14 : lt_error_set(lt_error_t **error,
98 : lt_error_type_t type,
99 : const char *message,
100 : ...)
101 : {
102 : va_list ap;
103 : void *traces[1024];
104 14 : lt_error_data_t *d = lt_mem_alloc_object(sizeof (lt_error_data_t));
105 : int size;
106 : lt_bool_t allocated;
107 :
108 14 : lt_return_val_if_fail (error != NULL, NULL);
109 :
110 14 : if (!d)
111 0 : goto bail0;
112 14 : if (!*error)
113 14 : *error = lt_error_new();
114 14 : if (!*error)
115 0 : goto bail0;
116 :
117 14 : d->type = type;
118 14 : va_start(ap, message);
119 14 : d->message = lt_strdup_vprintf(message, ap);
120 14 : va_end(ap);
121 :
122 : #ifdef _WIN32
123 : size = 0;
124 : #else
125 14 : size = backtrace(traces, 1024);
126 14 : if (size > 0)
127 14 : d->traces = backtrace_symbols(traces, size);
128 : #endif
129 14 : d->stack_size = size;
130 :
131 14 : lt_mem_add_ref(&d->parent, d->message, free);
132 14 : if (d->traces != NULL)
133 14 : lt_mem_add_ref(&d->parent, d->traces, free);
134 :
135 14 : allocated = (*error)->data == NULL;
136 14 : (*error)->data = lt_list_append((*error)->data, d, (lt_destroy_func_t)lt_mem_unref);
137 14 : if (allocated)
138 14 : lt_mem_add_ref(&(*error)->parent,
139 14 : (*error)->data,
140 : (lt_destroy_func_t)lt_list_free);
141 :
142 14 : return *error;
143 : bail0:
144 0 : lt_critical("Out of memory");
145 :
146 0 : return *error;
147 : }
148 :
149 : /**
150 : * lt_error_clear:
151 : * @error: a #lt_error_t
152 : *
153 : * Clean up all of the errors in @error.
154 : */
155 : void
156 0 : lt_error_clear(lt_error_t *error)
157 : {
158 0 : if (error) {
159 0 : lt_mem_delete_ref(&error->parent, error->data);
160 0 : error->data = NULL;
161 : }
162 0 : }
163 :
164 : /**
165 : * lt_error_is_set:
166 : * @error: a #lt_error_t
167 : * @type: a #lt_error_type_t
168 : *
169 : * Checks if @error contains @type of errors. if #LT_ERR_ANY is set to @type,
170 : * all the types of the errors are targeted. otherwise the result is filtered
171 : * out by @type.
172 : *
173 : * Returns: %TRUE if any, otherwise %FALSE
174 : */
175 : lt_bool_t
176 232 : lt_error_is_set(lt_error_t *error,
177 : lt_error_type_t type)
178 : {
179 232 : if (type == LT_ERR_ANY) {
180 232 : return error && error->data;
181 : } else {
182 0 : if (error && error->data) {
183 : lt_list_t *l;
184 :
185 0 : for (l = error->data; l != NULL; l = lt_list_next(l)) {
186 0 : lt_error_data_t *d = lt_list_value(l);
187 :
188 0 : if (d->type == type)
189 0 : return TRUE;
190 : }
191 : }
192 : }
193 :
194 0 : return FALSE;
195 : }
196 :
197 : /**
198 : * lt_error_print:
199 : * @error: a #lt_error_t
200 : * @type: a #lt_error_type_t
201 : *
202 : * Output the error messages in @error according to @type.
203 : */
204 : void
205 0 : lt_error_print(lt_error_t *error,
206 : lt_error_type_t type)
207 : {
208 : lt_list_t *l;
209 :
210 0 : if (lt_error_is_set(error, type)) {
211 0 : lt_warning("Error raised:");
212 0 : for (l = error->data; l != NULL; l = lt_list_next(l)) {
213 0 : lt_error_data_t *d = lt_list_value(l);
214 : int i;
215 :
216 0 : if (type == LT_ERR_ANY || type == d->type) {
217 0 : lt_warning(" %s", d->message);
218 0 : if (d->stack_size > 0) {
219 0 : lt_warning(" Backtraces:");
220 : } else {
221 0 : lt_warning(" No backtraces");
222 : }
223 0 : for (i = 1; i < d->stack_size; i++) {
224 0 : lt_warning(" %d. %s", i - 1, d->traces[i]);
225 : }
226 : }
227 : }
228 : }
229 0 : }
|