diff options
author | ncteisen <ncteisen@gmail.com> | 2017-03-13 10:27:18 -0700 |
---|---|---|
committer | ncteisen <ncteisen@gmail.com> | 2017-03-13 10:27:18 -0700 |
commit | 5398a9696398917090619f95530df7f4acaadba6 (patch) | |
tree | d2914fef8f93cbb4109dd9df6ad97ddbc2ed5fe0 /src/core/lib/iomgr | |
parent | d16df8fe1270acbbec45a3a0a52420049dc60a34 (diff) |
Fix copy and unref race cond bug
Diffstat (limited to 'src/core/lib/iomgr')
-rw-r--r-- | src/core/lib/iomgr/error.c | 8 | ||||
-rw-r--r-- | src/core/lib/iomgr/error_internal.h | 2 |
2 files changed, 6 insertions, 4 deletions
diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c index 7cdbe30198..f0e294b609 100644 --- a/src/core/lib/iomgr/error.c +++ b/src/core/lib/iomgr/error.c @@ -382,10 +382,12 @@ static grpc_error *copy_error_and_unref(grpc_error *in) { #ifdef GRPC_ERROR_REFCOUNT_DEBUG gpr_log(GPR_DEBUG, "%p create copying %p", out, in); #endif - memcpy(out, in, sizeof(*in) + in->arena_size * sizeof(intptr_t)); - out->arena_capacity = new_arena_capacity; - gpr_atm_no_barrier_store(&out->error_string, 0); gpr_ref_init(&out->refs, 1); + gpr_atm_no_barrier_store(&out->error_string, 0); + size_t skip = sizeof(gpr_refcount) + sizeof(gpr_atm); + memcpy((void *)out + skip, (void *)in + skip, + sizeof(*in) + (in->arena_size * sizeof(intptr_t)) - skip); + out->arena_capacity = new_arena_capacity; ref_strs(out); ref_errs(out); GRPC_ERROR_UNREF(in); diff --git a/src/core/lib/iomgr/error_internal.h b/src/core/lib/iomgr/error_internal.h index fb4814e41f..0718d31f23 100644 --- a/src/core/lib/iomgr/error_internal.h +++ b/src/core/lib/iomgr/error_internal.h @@ -48,12 +48,12 @@ struct grpc_linked_error { struct grpc_error { gpr_refcount refs; + gpr_atm error_string; uint8_t ints[GRPC_ERROR_INT_MAX]; uint8_t strs[GRPC_ERROR_STR_MAX]; uint8_t times[GRPC_ERROR_TIME_MAX]; uint8_t first_err; uint8_t last_err; - gpr_atm error_string; uint8_t arena_size; uint8_t arena_capacity; intptr_t arena[0]; |