forked from awslabs/aws-c-common
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patherror.c
159 lines (119 loc) · 4.41 KB
/
error.c
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
* Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 <aws/common/error.h>
#include <aws/common/common.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static AWS_THREAD_LOCAL int tl_last_error = 0;
static aws_error_handler_fn *s_global_handler = NULL;
static void *s_global_error_context = NULL;
static AWS_THREAD_LOCAL aws_error_handler_fn *tl_thread_handler = NULL;
AWS_THREAD_LOCAL void *tl_thread_handler_context = NULL;
#ifndef AWS_MAX_ERROR_SLOTS
# define AWS_MAX_ERROR_SLOTS 16
#endif
/* Since slot size is 00000100 00000000, to divide, we need to shift right by 10
* bits to find the slot, and to find the modulus, we use a binary and with
* 00000011 11111111 to find the index in that slot. The next three values
* define those constants */
#define AWS_ERROR_SLOT_SIZE 0x0400
#define SLOT_DIV_SHIFT 0x0A
#define SLOT_MASK 0x03FF
static const int MAX_ERROR_CODE = AWS_ERROR_SLOT_SIZE * AWS_MAX_ERROR_SLOTS;
static const struct aws_error_info_list *volatile ERROR_SLOTS[AWS_MAX_ERROR_SLOTS] = {0};
int aws_last_error(void) {
return tl_last_error;
}
static const struct aws_error_info *get_error_by_code(int err) {
if (err >= MAX_ERROR_CODE || err < 0) {
return NULL;
}
int slot_index = err >> SLOT_DIV_SHIFT;
int error_index = err & SLOT_MASK;
const struct aws_error_info_list *error_slot = ERROR_SLOTS[slot_index];
if (!error_slot || error_index >= error_slot->count) {
return NULL;
}
return &error_slot->error_list[error_index];
}
const char *aws_error_str(int err) {
const struct aws_error_info *error_info = get_error_by_code(err);
if (error_info) {
return error_info->error_str;
}
return "Unknown Error Code";
}
const char *aws_error_lib_name(int err) {
const struct aws_error_info *error_info = get_error_by_code(err);
if (error_info) {
return error_info->lib_name;
}
return "Unknown Error Code";
}
const char *aws_error_debug_str(int err) {
const struct aws_error_info *error_info = get_error_by_code(err);
if (error_info) {
return error_info->formatted_name;
}
return "Unknown Error Code";
}
int aws_raise_error(int err) {
tl_last_error = err;
if (tl_thread_handler) {
tl_thread_handler(tl_last_error, tl_thread_handler_context);
} else if (s_global_handler) {
s_global_handler(tl_last_error, s_global_error_context);
}
return AWS_OP_ERR;
}
void aws_reset_error(void) {
tl_last_error = 0;
}
void aws_restore_error(int err) {
tl_last_error = err;
}
aws_error_handler_fn *aws_set_global_error_handler_fn(aws_error_handler_fn *handler, void *ctx) {
aws_error_handler_fn *old_handler = s_global_handler;
s_global_handler = handler;
s_global_error_context = ctx;
return old_handler;
}
aws_error_handler_fn *aws_set_thread_local_error_handler_fn(aws_error_handler_fn *handler, void *ctx) {
aws_error_handler_fn *old_handler = tl_thread_handler;
tl_thread_handler = handler;
tl_thread_handler_context = ctx;
return old_handler;
}
void aws_register_error_info(const struct aws_error_info_list *error_info) {
/*
* We're not so worried about these asserts being removed in an NDEBUG build
* - we'll either segfault immediately (for the first two) or for the count
* assert, the registration will be ineffective.
*/
assert(error_info);
assert(error_info->error_list);
assert(error_info->count);
int min_range = error_info->error_list[0].error_code;
int slot_index = min_range >> SLOT_DIV_SHIFT;
assert(slot_index < AWS_MAX_ERROR_SLOTS && slot_index >= 0);
if (slot_index >= AWS_MAX_ERROR_SLOTS || slot_index < 0) {
/* This is an NDEBUG build apparently. Kill the process rather than
* corrupting heap. */
fprintf(stderr, "Bad error slot index 0x%016x\n", slot_index);
abort();
}
ERROR_SLOTS[slot_index] = error_info;
}