diff options
-rw-r--r-- | src/dl/dlfcn.go | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/src/dl/dlfcn.go b/src/dl/dlfcn.go index 3ab5abb..db8bd63 100644 --- a/src/dl/dlfcn.go +++ b/src/dl/dlfcn.go @@ -24,6 +24,7 @@ package dl import ( "errors" + "sync" "unsafe" ) @@ -32,6 +33,8 @@ import ( //#include <dlfcn.h> import "C" +var HandleClosedError = errors.New("Handle is already closed") + type Flag int // POSIX specifies these four flags to Open(). @@ -54,6 +57,8 @@ const ( type Handle struct { c unsafe.Pointer + o int + l sync.RWMutex } // Open a shared object file, returning a Handle to it, or an error. @@ -73,7 +78,7 @@ func Open(name string, flags Flag) (Handle, error) { if ptr == nil { return Handle{}, dlerror() } - return Handle{ptr}, nil + return Handle{c: ptr, o: 1}, nil } // Look up a symbol, and return a pointer to it. @@ -82,6 +87,13 @@ func Open(name string, flags Flag) (Handle, error) { // dl cannot obtain unsafe.Pointers without importing the unsafe // package explicitly. func (h Handle) Sym(symbol string) (uintptr, error) { + h.l.RLock() + defer h.l.RUnlock() + + if h.o == 0 { + return 0, HandleClosedError + } + symbolC := C.CString(symbol) defer C.free(unsafe.Pointer(symbolC)) @@ -97,11 +109,21 @@ func (h Handle) Sym(symbol string) (uintptr, error) { // count; if the reference count drops below 0, then the object is // unloaded. func (h Handle) Close() error { + h.l.Lock() + defer h.l.Unlock() + + if h.o == 0 { + return HandleClosedError + } + dlerror() r := C.dlclose(h.c) if r != 0 { return dlerror() } + if h.o == 1 { + h.o = 0 + } return nil } |