Commit 9b4aaa41 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

syscall: fix data races in LazyDLL/LazyProc

Reincarnation of https://golang.org/cl/6817086 (sent from another account).
It is ugly because sync.Once will cause allocation of a closure.
Fixes #4343.

R=golang-dev, bradfitz, alex.brainman
CC=golang-dev
https://golang.org/cl/6856046
parent 8b7ea648
...@@ -6,6 +6,8 @@ package syscall ...@@ -6,6 +6,8 @@ package syscall
import ( import (
"sync" "sync"
"sync/atomic"
"unsafe"
) )
// DLLError describes reasons for DLL load failures. // DLLError describes reasons for DLL load failures.
...@@ -166,7 +168,9 @@ type LazyDLL struct { ...@@ -166,7 +168,9 @@ type LazyDLL struct {
// Load loads DLL file d.Name into memory. It returns an error if fails. // Load loads DLL file d.Name into memory. It returns an error if fails.
// Load will not try to load DLL, if it is already loaded into memory. // Load will not try to load DLL, if it is already loaded into memory.
func (d *LazyDLL) Load() error { func (d *LazyDLL) Load() error {
if d.dll == nil { // Non-racy version of:
// if d.dll == nil {
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll))) == nil {
d.mu.Lock() d.mu.Lock()
defer d.mu.Unlock() defer d.mu.Unlock()
if d.dll == nil { if d.dll == nil {
...@@ -174,7 +178,9 @@ func (d *LazyDLL) Load() error { ...@@ -174,7 +178,9 @@ func (d *LazyDLL) Load() error {
if e != nil { if e != nil {
return e return e
} }
d.dll = dll // Non-racy version of:
// d.dll = dll
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)), unsafe.Pointer(dll))
} }
} }
return nil return nil
...@@ -217,7 +223,9 @@ type LazyProc struct { ...@@ -217,7 +223,9 @@ type LazyProc struct {
// an error if search fails. Find will not search procedure, // an error if search fails. Find will not search procedure,
// if it is already found and loaded into memory. // if it is already found and loaded into memory.
func (p *LazyProc) Find() error { func (p *LazyProc) Find() error {
if p.proc == nil { // Non-racy version of:
// if p.proc == nil {
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()
if p.proc == nil { if p.proc == nil {
...@@ -229,7 +237,9 @@ func (p *LazyProc) Find() error { ...@@ -229,7 +237,9 @@ func (p *LazyProc) Find() error {
if e != nil { if e != nil {
return e return e
} }
p.proc = proc // Non-racy version of:
// p.proc = proc
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
} }
} }
return nil return nil
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment