aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/iomgr
diff options
context:
space:
mode:
authorGravatar ncteisen <ncteisen@gmail.com>2017-03-13 10:27:18 -0700
committerGravatar ncteisen <ncteisen@gmail.com>2017-03-13 10:27:18 -0700
commit5398a9696398917090619f95530df7f4acaadba6 (patch)
treed2914fef8f93cbb4109dd9df6ad97ddbc2ed5fe0 /src/core/lib/iomgr
parentd16df8fe1270acbbec45a3a0a52420049dc60a34 (diff)
Fix copy and unref race cond bug
Diffstat (limited to 'src/core/lib/iomgr')
-rw-r--r--src/core/lib/iomgr/error.c8
-rw-r--r--src/core/lib/iomgr/error_internal.h2
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];