1 /* 2 * 3 * Copyright 2016 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 #include <grpc/support/port_platform.h> 19 20 #include "src/core/lib/iomgr/error.h" 21 22 #include <inttypes.h> 23 #include <string.h> 24 25 #include <grpc/status.h> 26 #include <grpc/support/alloc.h> 27 #include <grpc/support/log.h> 28 #include <grpc/support/string_util.h> 29 30 #ifdef GPR_WINDOWS 31 #include <grpc/support/log_windows.h> 32 #endif 33 34 #include "src/core/lib/debug/trace.h" 35 #include "src/core/lib/gpr/useful.h" 36 #include "src/core/lib/iomgr/error_internal.h" 37 #include "src/core/lib/profiling/timers.h" 38 #include "src/core/lib/slice/slice_internal.h" 39 40 grpc_core::DebugOnlyTraceFlag grpc_trace_error_refcount(false, 41 "error_refcount"); 42 grpc_core::DebugOnlyTraceFlag grpc_trace_closure(false, "closure"); 43 44 static const char* error_int_name(grpc_error_ints key) { 45 switch (key) { 46 case GRPC_ERROR_INT_ERRNO: 47 return "errno"; 48 case GRPC_ERROR_INT_FILE_LINE: 49 return "file_line"; 50 case GRPC_ERROR_INT_STREAM_ID: 51 return "stream_id"; 52 case GRPC_ERROR_INT_GRPC_STATUS: 53 return "grpc_status"; 54 case GRPC_ERROR_INT_OFFSET: 55 return "offset"; 56 case GRPC_ERROR_INT_INDEX: 57 return "index"; 58 case GRPC_ERROR_INT_SIZE: 59 return "size"; 60 case GRPC_ERROR_INT_HTTP2_ERROR: 61 return "http2_error"; 62 case GRPC_ERROR_INT_TSI_CODE: 63 return "tsi_code"; 64 case GRPC_ERROR_INT_SECURITY_STATUS: 65 return "security_status"; 66 case GRPC_ERROR_INT_FD: 67 return "fd"; 68 case GRPC_ERROR_INT_WSA_ERROR: 69 return "wsa_error"; 70 case GRPC_ERROR_INT_HTTP_STATUS: 71 return "http_status"; 72 case GRPC_ERROR_INT_LIMIT: 73 return "limit"; 74 case GRPC_ERROR_INT_OCCURRED_DURING_WRITE: 75 return "occurred_during_write"; 76 case GRPC_ERROR_INT_MAX: 77 GPR_UNREACHABLE_CODE(return "unknown"); 78 } 79 GPR_UNREACHABLE_CODE(return "unknown"); 80 } 81 82 static const char* error_str_name(grpc_error_strs key) { 83 switch (key) { 84 case GRPC_ERROR_STR_KEY: 85 return "key"; 86 case GRPC_ERROR_STR_VALUE: 87 return "value"; 88 case GRPC_ERROR_STR_DESCRIPTION: 89 return "description"; 90 case GRPC_ERROR_STR_OS_ERROR: 91 return "os_error"; 92 case GRPC_ERROR_STR_TARGET_ADDRESS: 93 return "target_address"; 94 case GRPC_ERROR_STR_SYSCALL: 95 return "syscall"; 96 case GRPC_ERROR_STR_FILE: 97 return "file"; 98 case GRPC_ERROR_STR_GRPC_MESSAGE: 99 return "grpc_message"; 100 case GRPC_ERROR_STR_RAW_BYTES: 101 return "raw_bytes"; 102 case GRPC_ERROR_STR_TSI_ERROR: 103 return "tsi_error"; 104 case GRPC_ERROR_STR_FILENAME: 105 return "filename"; 106 case GRPC_ERROR_STR_QUEUED_BUFFERS: 107 return "queued_buffers"; 108 case GRPC_ERROR_STR_MAX: 109 GPR_UNREACHABLE_CODE(return "unknown"); 110 } 111 GPR_UNREACHABLE_CODE(return "unknown"); 112 } 113 114 static const char* error_time_name(grpc_error_times key) { 115 switch (key) { 116 case GRPC_ERROR_TIME_CREATED: 117 return "created"; 118 case GRPC_ERROR_TIME_MAX: 119 GPR_UNREACHABLE_CODE(return "unknown"); 120 } 121 GPR_UNREACHABLE_CODE(return "unknown"); 122 } 123 124 bool grpc_error_is_special(grpc_error* err) { 125 return err == GRPC_ERROR_NONE || err == GRPC_ERROR_OOM || 126 err == GRPC_ERROR_CANCELLED; 127 } 128 129 #ifndef NDEBUG 130 grpc_error* grpc_error_ref(grpc_error* err, const char* file, int line) { 131 if (grpc_error_is_special(err)) return err; 132 if (grpc_trace_error_refcount.enabled()) { 133 gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d]", err, 134 gpr_atm_no_barrier_load(&err->atomics.refs.count), 135 gpr_atm_no_barrier_load(&err->atomics.refs.count) + 1, file, line); 136 } 137 gpr_ref(&err->atomics.refs); 138 return err; 139 } 140 #else 141 grpc_error* grpc_error_ref(grpc_error* err) { 142 if (grpc_error_is_special(err)) return err; 143 gpr_ref(&err->atomics.refs); 144 return err; 145 } 146 #endif 147 148 static void unref_errs(grpc_error* err) { 149 uint8_t slot = err->first_err; 150 while (slot != UINT8_MAX) { 151 grpc_linked_error* lerr = 152 reinterpret_cast<grpc_linked_error*>(err->arena + slot); 153 GRPC_ERROR_UNREF(lerr->err); 154 GPR_ASSERT(err->last_err == slot ? lerr->next == UINT8_MAX 155 : lerr->next != UINT8_MAX); 156 slot = lerr->next; 157 } 158 } 159 160 static void unref_slice(grpc_slice slice) { grpc_slice_unref_internal(slice); } 161 162 static void unref_strs(grpc_error* err) { 163 for (size_t which = 0; which < GRPC_ERROR_STR_MAX; ++which) { 164 uint8_t slot = err->strs[which]; 165 if (slot != UINT8_MAX) { 166 unref_slice(*reinterpret_cast<grpc_slice*>(err->arena + slot)); 167 } 168 } 169 } 170 171 static void error_destroy(grpc_error* err) { 172 GPR_ASSERT(!grpc_error_is_special(err)); 173 unref_errs(err); 174 unref_strs(err); 175 gpr_free((void*)gpr_atm_acq_load(&err->atomics.error_string)); 176 gpr_free(err); 177 } 178 179 #ifndef NDEBUG 180 void grpc_error_unref(grpc_error* err, const char* file, int line) { 181 if (grpc_error_is_special(err)) return; 182 if (grpc_trace_error_refcount.enabled()) { 183 gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d]", err, 184 gpr_atm_no_barrier_load(&err->atomics.refs.count), 185 gpr_atm_no_barrier_load(&err->atomics.refs.count) - 1, file, line); 186 } 187 if (gpr_unref(&err->atomics.refs)) { 188 error_destroy(err); 189 } 190 } 191 #else 192 void grpc_error_unref(grpc_error* err) { 193 if (grpc_error_is_special(err)) return; 194 if (gpr_unref(&err->atomics.refs)) { 195 error_destroy(err); 196 } 197 } 198 #endif 199 200 static uint8_t get_placement(grpc_error** err, size_t size) { 201 GPR_ASSERT(*err); 202 uint8_t slots = static_cast<uint8_t>(size / sizeof(intptr_t)); 203 if ((*err)->arena_size + slots > (*err)->arena_capacity) { 204 (*err)->arena_capacity = static_cast<uint8_t> GPR_MIN( 205 UINT8_MAX - 1, (3 * (*err)->arena_capacity / 2)); 206 if ((*err)->arena_size + slots > (*err)->arena_capacity) { 207 return UINT8_MAX; 208 } 209 #ifndef NDEBUG 210 grpc_error* orig = *err; 211 #endif 212 *err = static_cast<grpc_error*>(gpr_realloc( 213 *err, sizeof(grpc_error) + (*err)->arena_capacity * sizeof(intptr_t))); 214 #ifndef NDEBUG 215 if (grpc_trace_error_refcount.enabled()) { 216 if (*err != orig) { 217 gpr_log(GPR_DEBUG, "realloc %p -> %p", orig, *err); 218 } 219 } 220 #endif 221 } 222 uint8_t placement = (*err)->arena_size; 223 (*err)->arena_size = static_cast<uint8_t>((*err)->arena_size + slots); 224 return placement; 225 } 226 227 static void internal_set_int(grpc_error** err, grpc_error_ints which, 228 intptr_t value) { 229 uint8_t slot = (*err)->ints[which]; 230 if (slot == UINT8_MAX) { 231 slot = get_placement(err, sizeof(value)); 232 if (slot == UINT8_MAX) { 233 gpr_log(GPR_ERROR, "Error %p is full, dropping int {\"%s\":%" PRIiPTR "}", 234 *err, error_int_name(which), value); 235 return; 236 } 237 } 238 (*err)->ints[which] = slot; 239 (*err)->arena[slot] = value; 240 } 241 242 static void internal_set_str(grpc_error** err, grpc_error_strs which, 243 grpc_slice value) { 244 uint8_t slot = (*err)->strs[which]; 245 if (slot == UINT8_MAX) { 246 slot = get_placement(err, sizeof(value)); 247 if (slot == UINT8_MAX) { 248 const char* str = grpc_slice_to_c_string(value); 249 gpr_log(GPR_ERROR, "Error %p is full, dropping string {\"%s\":\"%s\"}", 250 *err, error_str_name(which), str); 251 gpr_free((void*)str); 252 return; 253 } 254 } else { 255 unref_slice(*reinterpret_cast<grpc_slice*>((*err)->arena + slot)); 256 } 257 (*err)->strs[which] = slot; 258 memcpy((*err)->arena + slot, &value, sizeof(value)); 259 } 260 261 static char* fmt_time(gpr_timespec tm); 262 static void internal_set_time(grpc_error** err, grpc_error_times which, 263 gpr_timespec value) { 264 uint8_t slot = (*err)->times[which]; 265 if (slot == UINT8_MAX) { 266 slot = get_placement(err, sizeof(value)); 267 if (slot == UINT8_MAX) { 268 const char* time_str = fmt_time(value); 269 gpr_log(GPR_ERROR, "Error %p is full, dropping \"%s\":\"%s\"}", *err, 270 error_time_name(which), time_str); 271 gpr_free((void*)time_str); 272 return; 273 } 274 } 275 (*err)->times[which] = slot; 276 memcpy((*err)->arena + slot, &value, sizeof(value)); 277 } 278 279 static void internal_add_error(grpc_error** err, grpc_error* new_err) { 280 grpc_linked_error new_last = {new_err, UINT8_MAX}; 281 uint8_t slot = get_placement(err, sizeof(grpc_linked_error)); 282 if (slot == UINT8_MAX) { 283 gpr_log(GPR_ERROR, "Error %p is full, dropping error %p = %s", *err, 284 new_err, grpc_error_string(new_err)); 285 GRPC_ERROR_UNREF(new_err); 286 return; 287 } 288 if ((*err)->first_err == UINT8_MAX) { 289 GPR_ASSERT((*err)->last_err == UINT8_MAX); 290 (*err)->last_err = slot; 291 (*err)->first_err = slot; 292 } else { 293 GPR_ASSERT((*err)->last_err != UINT8_MAX); 294 grpc_linked_error* old_last = 295 reinterpret_cast<grpc_linked_error*>((*err)->arena + (*err)->last_err); 296 old_last->next = slot; 297 (*err)->last_err = slot; 298 } 299 memcpy((*err)->arena + slot, &new_last, sizeof(grpc_linked_error)); 300 } 301 302 #define SLOTS_PER_INT (sizeof(intptr_t) / sizeof(intptr_t)) 303 #define SLOTS_PER_STR (sizeof(grpc_slice) / sizeof(intptr_t)) 304 #define SLOTS_PER_TIME (sizeof(gpr_timespec) / sizeof(intptr_t)) 305 #define SLOTS_PER_LINKED_ERROR (sizeof(grpc_linked_error) / sizeof(intptr_t)) 306 307 // size of storing one int and two slices and a timespec. For line, desc, file, 308 // and time created 309 #define DEFAULT_ERROR_CAPACITY \ 310 (SLOTS_PER_INT + (SLOTS_PER_STR * 2) + SLOTS_PER_TIME) 311 312 // It is very common to include and extra int and string in an error 313 #define SURPLUS_CAPACITY (2 * SLOTS_PER_INT + SLOTS_PER_TIME) 314 315 static bool g_error_creation_allowed = true; 316 317 void grpc_disable_error_creation() { g_error_creation_allowed = false; } 318 319 void grpc_enable_error_creation() { g_error_creation_allowed = true; } 320 321 grpc_error* grpc_error_create(const char* file, int line, grpc_slice desc, 322 grpc_error** referencing, 323 size_t num_referencing) { 324 GPR_TIMER_SCOPE("grpc_error_create", 0); 325 uint8_t initial_arena_capacity = static_cast<uint8_t>( 326 DEFAULT_ERROR_CAPACITY + 327 static_cast<uint8_t>(num_referencing * SLOTS_PER_LINKED_ERROR) + 328 SURPLUS_CAPACITY); 329 grpc_error* err = static_cast<grpc_error*>( 330 gpr_malloc(sizeof(*err) + initial_arena_capacity * sizeof(intptr_t))); 331 if (err == nullptr) { // TODO(ctiller): make gpr_malloc return NULL 332 return GRPC_ERROR_OOM; 333 } 334 #ifndef NDEBUG 335 if (!g_error_creation_allowed) { 336 gpr_log(GPR_ERROR, 337 "Error creation occurred when error creation was disabled [%s:%d]", 338 file, line); 339 abort(); 340 } 341 if (grpc_trace_error_refcount.enabled()) { 342 gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line); 343 } 344 #endif 345 346 err->arena_size = 0; 347 err->arena_capacity = initial_arena_capacity; 348 err->first_err = UINT8_MAX; 349 err->last_err = UINT8_MAX; 350 351 memset(err->ints, UINT8_MAX, GRPC_ERROR_INT_MAX); 352 memset(err->strs, UINT8_MAX, GRPC_ERROR_STR_MAX); 353 memset(err->times, UINT8_MAX, GRPC_ERROR_TIME_MAX); 354 355 internal_set_int(&err, GRPC_ERROR_INT_FILE_LINE, line); 356 internal_set_str(&err, GRPC_ERROR_STR_FILE, 357 grpc_slice_from_static_string(file)); 358 internal_set_str(&err, GRPC_ERROR_STR_DESCRIPTION, desc); 359 360 for (size_t i = 0; i < num_referencing; ++i) { 361 if (referencing[i] == GRPC_ERROR_NONE) continue; 362 internal_add_error( 363 &err, 364 GRPC_ERROR_REF( 365 referencing[i])); // TODO(ncteisen), change ownership semantics 366 } 367 368 internal_set_time(&err, GRPC_ERROR_TIME_CREATED, gpr_now(GPR_CLOCK_REALTIME)); 369 370 gpr_atm_no_barrier_store(&err->atomics.error_string, 0); 371 gpr_ref_init(&err->atomics.refs, 1); 372 return err; 373 } 374 375 static void ref_strs(grpc_error* err) { 376 for (size_t i = 0; i < GRPC_ERROR_STR_MAX; ++i) { 377 uint8_t slot = err->strs[i]; 378 if (slot != UINT8_MAX) { 379 grpc_slice_ref_internal( 380 *reinterpret_cast<grpc_slice*>(err->arena + slot)); 381 } 382 } 383 } 384 385 static void ref_errs(grpc_error* err) { 386 uint8_t slot = err->first_err; 387 while (slot != UINT8_MAX) { 388 grpc_linked_error* lerr = 389 reinterpret_cast<grpc_linked_error*>(err->arena + slot); 390 GRPC_ERROR_REF(lerr->err); 391 slot = lerr->next; 392 } 393 } 394 395 static grpc_error* copy_error_and_unref(grpc_error* in) { 396 GPR_TIMER_SCOPE("copy_error_and_unref", 0); 397 grpc_error* out; 398 if (grpc_error_is_special(in)) { 399 out = GRPC_ERROR_CREATE_FROM_STATIC_STRING("unknown"); 400 if (in == GRPC_ERROR_NONE) { 401 internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, 402 grpc_slice_from_static_string("no error")); 403 internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK); 404 } else if (in == GRPC_ERROR_OOM) { 405 internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, 406 grpc_slice_from_static_string("oom")); 407 } else if (in == GRPC_ERROR_CANCELLED) { 408 internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, 409 grpc_slice_from_static_string("cancelled")); 410 internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED); 411 } 412 } else if (gpr_ref_is_unique(&in->atomics.refs)) { 413 out = in; 414 } else { 415 uint8_t new_arena_capacity = in->arena_capacity; 416 // the returned err will be added to, so we ensure this is room to avoid 417 // unneeded allocations. 418 if (in->arena_capacity - in->arena_size < 419 static_cast<uint8_t> SLOTS_PER_STR) { 420 new_arena_capacity = static_cast<uint8_t>(3 * new_arena_capacity / 2); 421 } 422 out = static_cast<grpc_error*>( 423 gpr_malloc(sizeof(*in) + new_arena_capacity * sizeof(intptr_t))); 424 #ifndef NDEBUG 425 if (grpc_trace_error_refcount.enabled()) { 426 gpr_log(GPR_DEBUG, "%p create copying %p", out, in); 427 } 428 #endif 429 // bulk memcpy of the rest of the struct. 430 size_t skip = sizeof(&out->atomics); 431 memcpy((void*)((uintptr_t)out + skip), (void*)((uintptr_t)in + skip), 432 sizeof(*in) + (in->arena_size * sizeof(intptr_t)) - skip); 433 // manually set the atomics and the new capacity 434 gpr_atm_no_barrier_store(&out->atomics.error_string, 0); 435 gpr_ref_init(&out->atomics.refs, 1); 436 out->arena_capacity = new_arena_capacity; 437 ref_strs(out); 438 ref_errs(out); 439 GRPC_ERROR_UNREF(in); 440 } 441 return out; 442 } 443 444 grpc_error* grpc_error_set_int(grpc_error* src, grpc_error_ints which, 445 intptr_t value) { 446 GPR_TIMER_SCOPE("grpc_error_set_int", 0); 447 grpc_error* new_err = copy_error_and_unref(src); 448 internal_set_int(&new_err, which, value); 449 return new_err; 450 } 451 452 typedef struct { 453 grpc_error* error; 454 grpc_status_code code; 455 const char* msg; 456 } special_error_status_map; 457 static special_error_status_map error_status_map[] = { 458 {GRPC_ERROR_NONE, GRPC_STATUS_OK, ""}, 459 {GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "Cancelled"}, 460 {GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"}, 461 }; 462 463 bool grpc_error_get_int(grpc_error* err, grpc_error_ints which, intptr_t* p) { 464 GPR_TIMER_SCOPE("grpc_error_get_int", 0); 465 if (grpc_error_is_special(err)) { 466 if (which == GRPC_ERROR_INT_GRPC_STATUS) { 467 for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) { 468 if (error_status_map[i].error == err) { 469 if (p != nullptr) *p = error_status_map[i].code; 470 return true; 471 } 472 } 473 } 474 return false; 475 } 476 uint8_t slot = err->ints[which]; 477 if (slot != UINT8_MAX) { 478 if (p != nullptr) *p = err->arena[slot]; 479 return true; 480 } 481 return false; 482 } 483 484 grpc_error* grpc_error_set_str(grpc_error* src, grpc_error_strs which, 485 grpc_slice str) { 486 GPR_TIMER_SCOPE("grpc_error_set_str", 0); 487 grpc_error* new_err = copy_error_and_unref(src); 488 internal_set_str(&new_err, which, str); 489 return new_err; 490 } 491 492 bool grpc_error_get_str(grpc_error* err, grpc_error_strs which, 493 grpc_slice* str) { 494 if (grpc_error_is_special(err)) { 495 if (which == GRPC_ERROR_STR_GRPC_MESSAGE) { 496 for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) { 497 if (error_status_map[i].error == err) { 498 *str = grpc_slice_from_static_string(error_status_map[i].msg); 499 return true; 500 } 501 } 502 } 503 return false; 504 } 505 uint8_t slot = err->strs[which]; 506 if (slot != UINT8_MAX) { 507 *str = *reinterpret_cast<grpc_slice*>(err->arena + slot); 508 return true; 509 } else { 510 return false; 511 } 512 } 513 514 grpc_error* grpc_error_add_child(grpc_error* src, grpc_error* child) { 515 GPR_TIMER_SCOPE("grpc_error_add_child", 0); 516 if (src != GRPC_ERROR_NONE) { 517 if (child == GRPC_ERROR_NONE) { 518 /* \a child is empty. Simply return the ref to \a src */ 519 return src; 520 } else if (child != src) { 521 grpc_error* new_err = copy_error_and_unref(src); 522 internal_add_error(&new_err, child); 523 return new_err; 524 } else { 525 /* \a src and \a child are the same. Drop one of the references and return 526 * the other */ 527 GRPC_ERROR_UNREF(child); 528 return src; 529 } 530 } else { 531 /* \a src is empty. Simply return the ref to \a child */ 532 return child; 533 } 534 } 535 536 static const char* no_error_string = "\"No Error\""; 537 static const char* oom_error_string = "\"Out of memory\""; 538 static const char* cancelled_error_string = "\"Cancelled\""; 539 540 typedef struct { 541 char* key; 542 char* value; 543 } kv_pair; 544 545 typedef struct { 546 kv_pair* kvs; 547 size_t num_kvs; 548 size_t cap_kvs; 549 } kv_pairs; 550 551 static void append_chr(char c, char** s, size_t* sz, size_t* cap) { 552 if (*sz == *cap) { 553 *cap = GPR_MAX(8, 3 * *cap / 2); 554 *s = static_cast<char*>(gpr_realloc(*s, *cap)); 555 } 556 (*s)[(*sz)++] = c; 557 } 558 559 static void append_str(const char* str, char** s, size_t* sz, size_t* cap) { 560 for (const char* c = str; *c; c++) { 561 append_chr(*c, s, sz, cap); 562 } 563 } 564 565 static void append_esc_str(const uint8_t* str, size_t len, char** s, size_t* sz, 566 size_t* cap) { 567 static const char* hex = "0123456789abcdef"; 568 append_chr('"', s, sz, cap); 569 for (size_t i = 0; i < len; i++, str++) { 570 if (*str < 32 || *str >= 127) { 571 append_chr('\\', s, sz, cap); 572 switch (*str) { 573 case '\b': 574 append_chr('b', s, sz, cap); 575 break; 576 case '\f': 577 append_chr('f', s, sz, cap); 578 break; 579 case '\n': 580 append_chr('n', s, sz, cap); 581 break; 582 case '\r': 583 append_chr('r', s, sz, cap); 584 break; 585 case '\t': 586 append_chr('t', s, sz, cap); 587 break; 588 default: 589 append_chr('u', s, sz, cap); 590 append_chr('0', s, sz, cap); 591 append_chr('0', s, sz, cap); 592 append_chr(hex[*str >> 4], s, sz, cap); 593 append_chr(hex[*str & 0x0f], s, sz, cap); 594 break; 595 } 596 } else { 597 append_chr(static_cast<char>(*str), s, sz, cap); 598 } 599 } 600 append_chr('"', s, sz, cap); 601 } 602 603 static void append_kv(kv_pairs* kvs, char* key, char* value) { 604 if (kvs->num_kvs == kvs->cap_kvs) { 605 kvs->cap_kvs = GPR_MAX(3 * kvs->cap_kvs / 2, 4); 606 kvs->kvs = static_cast<kv_pair*>( 607 gpr_realloc(kvs->kvs, sizeof(*kvs->kvs) * kvs->cap_kvs)); 608 } 609 kvs->kvs[kvs->num_kvs].key = key; 610 kvs->kvs[kvs->num_kvs].value = value; 611 kvs->num_kvs++; 612 } 613 614 static char* key_int(grpc_error_ints which) { 615 return gpr_strdup(error_int_name(which)); 616 } 617 618 static char* fmt_int(intptr_t p) { 619 char* s; 620 gpr_asprintf(&s, "%" PRIdPTR, p); 621 return s; 622 } 623 624 static void collect_ints_kvs(grpc_error* err, kv_pairs* kvs) { 625 for (size_t which = 0; which < GRPC_ERROR_INT_MAX; ++which) { 626 uint8_t slot = err->ints[which]; 627 if (slot != UINT8_MAX) { 628 append_kv(kvs, key_int(static_cast<grpc_error_ints>(which)), 629 fmt_int(err->arena[slot])); 630 } 631 } 632 } 633 634 static char* key_str(grpc_error_strs which) { 635 return gpr_strdup(error_str_name(which)); 636 } 637 638 static char* fmt_str(grpc_slice slice) { 639 char* s = nullptr; 640 size_t sz = 0; 641 size_t cap = 0; 642 append_esc_str((const uint8_t*)GRPC_SLICE_START_PTR(slice), 643 GRPC_SLICE_LENGTH(slice), &s, &sz, &cap); 644 append_chr(0, &s, &sz, &cap); 645 return s; 646 } 647 648 static void collect_strs_kvs(grpc_error* err, kv_pairs* kvs) { 649 for (size_t which = 0; which < GRPC_ERROR_STR_MAX; ++which) { 650 uint8_t slot = err->strs[which]; 651 if (slot != UINT8_MAX) { 652 append_kv(kvs, key_str(static_cast<grpc_error_strs>(which)), 653 fmt_str(*reinterpret_cast<grpc_slice*>(err->arena + slot))); 654 } 655 } 656 } 657 658 static char* key_time(grpc_error_times which) { 659 return gpr_strdup(error_time_name(which)); 660 } 661 662 static char* fmt_time(gpr_timespec tm) { 663 char* out; 664 const char* pfx = "!!"; 665 switch (tm.clock_type) { 666 case GPR_CLOCK_MONOTONIC: 667 pfx = "@monotonic:"; 668 break; 669 case GPR_CLOCK_REALTIME: 670 pfx = "@"; 671 break; 672 case GPR_CLOCK_PRECISE: 673 pfx = "@precise:"; 674 break; 675 case GPR_TIMESPAN: 676 pfx = ""; 677 break; 678 } 679 gpr_asprintf(&out, "\"%s%" PRId64 ".%09d\"", pfx, tm.tv_sec, tm.tv_nsec); 680 return out; 681 } 682 683 static void collect_times_kvs(grpc_error* err, kv_pairs* kvs) { 684 for (size_t which = 0; which < GRPC_ERROR_TIME_MAX; ++which) { 685 uint8_t slot = err->times[which]; 686 if (slot != UINT8_MAX) { 687 append_kv(kvs, key_time(static_cast<grpc_error_times>(which)), 688 fmt_time(*reinterpret_cast<gpr_timespec*>(err->arena + slot))); 689 } 690 } 691 } 692 693 static void add_errs(grpc_error* err, char** s, size_t* sz, size_t* cap) { 694 uint8_t slot = err->first_err; 695 bool first = true; 696 while (slot != UINT8_MAX) { 697 grpc_linked_error* lerr = 698 reinterpret_cast<grpc_linked_error*>(err->arena + slot); 699 if (!first) append_chr(',', s, sz, cap); 700 first = false; 701 const char* e = grpc_error_string(lerr->err); 702 append_str(e, s, sz, cap); 703 GPR_ASSERT(err->last_err == slot ? lerr->next == UINT8_MAX 704 : lerr->next != UINT8_MAX); 705 slot = lerr->next; 706 } 707 } 708 709 static char* errs_string(grpc_error* err) { 710 char* s = nullptr; 711 size_t sz = 0; 712 size_t cap = 0; 713 append_chr('[', &s, &sz, &cap); 714 add_errs(err, &s, &sz, &cap); 715 append_chr(']', &s, &sz, &cap); 716 append_chr(0, &s, &sz, &cap); 717 return s; 718 } 719 720 static int cmp_kvs(const void* a, const void* b) { 721 const kv_pair* ka = static_cast<const kv_pair*>(a); 722 const kv_pair* kb = static_cast<const kv_pair*>(b); 723 return strcmp(ka->key, kb->key); 724 } 725 726 static char* finish_kvs(kv_pairs* kvs) { 727 char* s = nullptr; 728 size_t sz = 0; 729 size_t cap = 0; 730 731 append_chr('{', &s, &sz, &cap); 732 for (size_t i = 0; i < kvs->num_kvs; i++) { 733 if (i != 0) append_chr(',', &s, &sz, &cap); 734 append_esc_str(reinterpret_cast<const uint8_t*>(kvs->kvs[i].key), 735 strlen(kvs->kvs[i].key), &s, &sz, &cap); 736 gpr_free(kvs->kvs[i].key); 737 append_chr(':', &s, &sz, &cap); 738 append_str(kvs->kvs[i].value, &s, &sz, &cap); 739 gpr_free(kvs->kvs[i].value); 740 } 741 append_chr('}', &s, &sz, &cap); 742 append_chr(0, &s, &sz, &cap); 743 744 gpr_free(kvs->kvs); 745 return s; 746 } 747 748 const char* grpc_error_string(grpc_error* err) { 749 GPR_TIMER_SCOPE("grpc_error_string", 0); 750 if (err == GRPC_ERROR_NONE) return no_error_string; 751 if (err == GRPC_ERROR_OOM) return oom_error_string; 752 if (err == GRPC_ERROR_CANCELLED) return cancelled_error_string; 753 754 void* p = (void*)gpr_atm_acq_load(&err->atomics.error_string); 755 if (p != nullptr) { 756 return static_cast<const char*>(p); 757 } 758 759 kv_pairs kvs; 760 memset(&kvs, 0, sizeof(kvs)); 761 762 collect_ints_kvs(err, &kvs); 763 collect_strs_kvs(err, &kvs); 764 collect_times_kvs(err, &kvs); 765 if (err->first_err != UINT8_MAX) { 766 append_kv(&kvs, gpr_strdup("referenced_errors"), errs_string(err)); 767 } 768 769 qsort(kvs.kvs, kvs.num_kvs, sizeof(kv_pair), cmp_kvs); 770 771 char* out = finish_kvs(&kvs); 772 773 if (!gpr_atm_rel_cas(&err->atomics.error_string, 0, (gpr_atm)out)) { 774 gpr_free(out); 775 out = (char*)gpr_atm_acq_load(&err->atomics.error_string); 776 } 777 778 return out; 779 } 780 781 grpc_error* grpc_os_error(const char* file, int line, int err, 782 const char* call_name) { 783 return grpc_error_set_str( 784 grpc_error_set_str( 785 grpc_error_set_int( 786 grpc_error_create(file, line, 787 grpc_slice_from_static_string("OS Error"), 788 nullptr, 0), 789 GRPC_ERROR_INT_ERRNO, err), 790 GRPC_ERROR_STR_OS_ERROR, 791 grpc_slice_from_static_string(strerror(err))), 792 GRPC_ERROR_STR_SYSCALL, grpc_slice_from_copied_string(call_name)); 793 } 794 795 #ifdef GPR_WINDOWS 796 grpc_error* grpc_wsa_error(const char* file, int line, int err, 797 const char* call_name) { 798 char* utf8_message = gpr_format_message(err); 799 grpc_error* error = grpc_error_set_str( 800 grpc_error_set_str( 801 grpc_error_set_int( 802 grpc_error_create(file, line, 803 grpc_slice_from_static_string("OS Error"), NULL, 804 0), 805 GRPC_ERROR_INT_WSA_ERROR, err), 806 GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_copied_string(utf8_message)), 807 GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string(call_name)); 808 gpr_free(utf8_message); 809 return error; 810 } 811 #endif 812 813 bool grpc_log_if_error(const char* what, grpc_error* error, const char* file, 814 int line) { 815 if (error == GRPC_ERROR_NONE) return true; 816 const char* msg = grpc_error_string(error); 817 gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "%s: %s", what, msg); 818 GRPC_ERROR_UNREF(error); 819 return false; 820 } 821