-
Notifications
You must be signed in to change notification settings - Fork 24
/
error.cpp
125 lines (102 loc) · 3.04 KB
/
error.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* Error functions.
*
* Copyright 2010, Michael Cohen <sucdette@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#if !defined( WIN32 )
#include <pthread.h>
#endif
#include "aff4_errors.h"
#include "class.h"
#define ERROR_BUFF_SIZE 10240
// Windows version not truely threadsafe for now
#if defined( WIN32 )
static char global_error_buffer[ERROR_BUFF_SIZE];
static int global_error_type = 0;
#else
/** These slots carry the TLS error keys */
static pthread_key_t error_str_slot;
static pthread_once_t error_once = PTHREAD_ONCE_INIT;
static pthread_key_t error_value_slot;
#endif
#if defined( WIN32 )
static void error_init(void) {
memset(global_error_buffer, 0, sizeof(global_error_buffer));
};
#else
static void error_init(void);
void error_dest(void *slot) {
if(slot) talloc_free(slot);
};
void error_init(void) {
// We create the error buffer slots
if(pthread_key_create(&error_str_slot, error_dest) ||
pthread_key_create(&error_value_slot, error_dest)) {
printf("Unable to set up TLS variables\n");
abort();
};
};
#endif
DLL_PUBLIC void *aff4_raise_errors(int t, const char *reason, ...) {
char *error_buffer;
char tmp[ERROR_BUFF_SIZE];
// This has to succeed:
int *type = aff4_get_current_error(&error_buffer);
if(reason) {
va_list ap;
va_start(ap, reason);
vsnprintf(tmp, ERROR_BUFF_SIZE-1, reason,ap);
tmp[ERROR_BUFF_SIZE-1]=0;
va_end(ap);
};
if(*type == EZero) {
*error_buffer = 0;
//update the error type
*type = t;
} else {
strncat(error_buffer, "\n", ERROR_BUFF_SIZE -1 );
};
strncat(error_buffer, tmp, ERROR_BUFF_SIZE-1);
return NULL;
};
#if defined( WIN32 )
DLL_PUBLIC int *aff4_get_current_error(char **error_buffer) {
if(error_buffer != NULL) {
*error_buffer = global_error_buffer;
};
return &global_error_type;
};
#else
DLL_PUBLIC int *aff4_get_current_error(char **error_buffer) {
int *type;
(void) pthread_once(&error_once, error_init);
type = (int *) pthread_getspecific(error_value_slot);
// This is optional
if(error_buffer != NULL) {
*error_buffer = (char *) pthread_getspecific(error_str_slot);
// If TLS buffers are not set we need to create them
// TODO: the TLS buffers need to be freed on exit.
if(*error_buffer == NULL) {
*error_buffer = (char *) talloc_size(NULL, ERROR_BUFF_SIZE);
pthread_setspecific(error_str_slot, *error_buffer);
};
};
if(!type) {
type = (int *) talloc_size(NULL, ERROR_BUFF_SIZE);
pthread_setspecific(error_value_slot, type);
};
return type;
};
#endif