From 04fc88776187a3c9c35a575eef65a7e9b9276e6d Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 2 Mar 2017 06:30:26 -0800 Subject: [PATCH] runtime: delay marking maps as writing until after first alg call Fixes #19359 Change-Id: I196b47cf0471915b6dc63785e8542aa1876ff695 Reviewed-on: https://go-review.googlesource.com/37665 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- src/runtime/hashmap.go | 12 +++++++++--- test/fixedbugs/issue19359.go | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 test/fixedbugs/issue19359.go diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go index 1f2dafa91e..5fd8e882bb 100644 --- a/src/runtime/hashmap.go +++ b/src/runtime/hashmap.go @@ -498,11 +498,13 @@ func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer { if h.flags&hashWriting != 0 { throw("concurrent map writes") } - h.flags |= hashWriting - alg := t.key.alg hash := alg.hash(key, uintptr(h.hash0)) + // Set hashWriting after calling alg.hash, since alg.hash may panic, + // in which case we have not actually done a write. + h.flags |= hashWriting + if h.buckets == nil { h.buckets = newarray(t.bucket, 1) } @@ -611,10 +613,14 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) { if h.flags&hashWriting != 0 { throw("concurrent map writes") } - h.flags |= hashWriting alg := t.key.alg hash := alg.hash(key, uintptr(h.hash0)) + + // Set hashWriting after calling alg.hash, since alg.hash may panic, + // in which case we have not actually done a write (delete). + h.flags |= hashWriting + bucket := hash & (uintptr(1)<