Prevent hangs in OncePer when the callback panics

If the callback passed to Once panics it was leaving the waiter
in place that would never be completed.  Move writing the value
and signalling the waiter to defer.

Test: TestOncePerPanic
Change-Id: Icc4d3b779a79914fcd881d61d38dffcc2f591c39
diff --git a/android/onceper.go b/android/onceper.go
index 5ad17fa..ff865c2 100644
--- a/android/onceper.go
+++ b/android/onceper.go
@@ -40,7 +40,8 @@
 }
 
 // Once computes a value the first time it is called with a given key per OncePer, and returns the
-// value without recomputing when called with the same key.  key must be hashable.
+// value without recomputing when called with the same key.  key must be hashable.  If value panics
+// the panic will be propagated but the next call to Once with the same key will return nil.
 func (once *OncePer) Once(key OnceKey, value func() interface{}) interface{} {
 	// Fast path: check if the key is already in the map
 	if v, ok := once.values.Load(key); ok {
@@ -54,10 +55,15 @@
 		return once.maybeWaitFor(key, v)
 	}
 
-	// The waiter is inserted, call the value constructor, store it, and signal the waiter
-	v := value()
-	once.values.Store(key, v)
-	close(waiter)
+	// The waiter is inserted, call the value constructor, store it, and signal the waiter.  Use defer in case
+	// the function panics.
+	var v interface{}
+	defer func() {
+		once.values.Store(key, v)
+		close(waiter)
+	}()
+
+	v = value()
 
 	return v
 }