From b9b446cf9e2b13d9b6a944de5edeafb4b7bbe2ba Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Sat, 16 Oct 2021 01:19:52 +0200 Subject: [PATCH 1/2] Use mutex on pointer store/restore, only important that it is lock-free on fetch --- longtaillib/longtaillib.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/longtaillib/longtaillib.go b/longtaillib/longtaillib.go index dc332990..0b89a455 100644 --- a/longtaillib/longtaillib.go +++ b/longtaillib/longtaillib.go @@ -7,7 +7,7 @@ import ( "fmt" "os" "reflect" - "sync/atomic" + "sync" "unsafe" "github.com/pkg/errors" @@ -362,22 +362,28 @@ var pointerIndex uint32 var pointerStore [1024]interface{} var pointerIndexer = (*[1 << 30]C.uint32_t)(C.malloc(4 * 1024)) +var refPointerSync sync.Mutex + func SavePointer(v interface{}) unsafe.Pointer { if v == nil { return nil } + refPointerSync.Lock() + defer refPointerSync.Unlock() - newPointerIndex := (atomic.AddUint32(&pointerIndex, 1)) % 1024 - startPointerIndex := newPointerIndex - for pointerStore[newPointerIndex] != nil { - newPointerIndex = (atomic.AddUint32(&pointerIndex, 1)) % 1024 - if newPointerIndex == startPointerIndex { + startPointerIndex := pointerIndex + for pointerStore[pointerIndex] != nil { + pointerIndex++ + if pointerIndex == 1024 { + pointerIndex = 0 + } + if pointerIndex == startPointerIndex { return nil } } - pointerIndexer[newPointerIndex] = C.uint32_t(newPointerIndex) - pointerStore[newPointerIndex] = v - return unsafe.Pointer(&pointerIndexer[newPointerIndex]) + pointerIndexer[pointerIndex] = C.uint32_t(pointerIndex) + pointerStore[pointerIndex] = v + return unsafe.Pointer(&pointerIndexer[pointerIndex]) } func RestorePointer(ptr unsafe.Pointer) (v interface{}) { @@ -395,6 +401,8 @@ func UnrefPointer(ptr unsafe.Pointer) { if ptr == nil { return } + refPointerSync.Lock() + defer refPointerSync.Unlock() p := (*C.uint32_t)(ptr) index := uint32(*p) From 79b2b1cbdee9ec63695db631ad962e862ff3767a Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Sat, 16 Oct 2021 01:20:06 +0200 Subject: [PATCH 2/2] Validate return value of SavePointer --- longtaillib/longtaillib.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/longtaillib/longtaillib.go b/longtaillib/longtaillib.go index 0b89a455..dd8201bd 100644 --- a/longtaillib/longtaillib.go +++ b/longtaillib/longtaillib.go @@ -1793,6 +1793,9 @@ func ReadStoreIndexFromBuffer(buffer []byte) (Longtail_StoreIndex, error) { // CreateProgressAPI ... func CreateProgressAPI(progress ProgressAPI) Longtail_ProgressAPI { cContext := SavePointer(progress) + if cContext == nil { + return Longtail_ProgressAPI{} + } progressAPIProxy := C.CreateProgressProxyAPI(cContext) return Longtail_ProgressAPI{cProgressAPI: progressAPIProxy} } @@ -1817,6 +1820,9 @@ func ProgressAPIProxy_Dispose(api *C.struct_Longtail_API) { // CreatePathFilterAPI ... func CreatePathFilterAPI(pathFilter PathFilterAPI) Longtail_PathFilterAPI { cContext := SavePointer(pathFilter) + if cContext == nil { + return Longtail_PathFilterAPI{} + } pathFilterAPIProxy := C.CreatePathFilterProxyAPI(cContext) return Longtail_PathFilterAPI{cPathFilterAPI: pathFilterAPIProxy} } @@ -1847,6 +1853,9 @@ func PathFilterAPIProxy_Dispose(api *C.struct_Longtail_API) { // CreateAsyncPutStoredBlockAPI ... func CreateAsyncPutStoredBlockAPI(asyncComplete AsyncPutStoredBlockAPI) Longtail_AsyncPutStoredBlockAPI { cContext := SavePointer(asyncComplete) + if cContext == nil { + return Longtail_AsyncPutStoredBlockAPI{} + } asyncCompleteAPIProxy := C.CreateAsyncPutStoredBlockAPI(cContext) return Longtail_AsyncPutStoredBlockAPI{cAsyncCompleteAPI: asyncCompleteAPIProxy} } @@ -1873,6 +1882,9 @@ func AsyncPutStoredBlockAPIProxy_Dispose(api *C.struct_Longtail_API) { // CreateAsyncGetStoredBlockAPI ... func CreateAsyncGetStoredBlockAPI(asyncComplete AsyncGetStoredBlockAPI) Longtail_AsyncGetStoredBlockAPI { cContext := SavePointer(asyncComplete) + if cContext == nil { + return Longtail_AsyncGetStoredBlockAPI{} + } asyncCompleteAPIProxy := C.CreateAsyncGetStoredBlockAPI(cContext) return Longtail_AsyncGetStoredBlockAPI{cAsyncCompleteAPI: asyncCompleteAPIProxy} } @@ -1899,6 +1911,9 @@ func AsyncGetStoredBlockAPIProxy_Dispose(api *C.struct_Longtail_API) { // CreateAsyncGetExistingContentAPI ... func CreateAsyncGetExistingContentAPI(asyncComplete AsyncGetExistingContentAPI) Longtail_AsyncGetExistingContentAPI { cContext := SavePointer(asyncComplete) + if cContext == nil { + return Longtail_AsyncGetExistingContentAPI{} + } asyncCompleteAPIProxy := C.CreateAsyncGetExistingContentAPI(cContext) return Longtail_AsyncGetExistingContentAPI{cAsyncCompleteAPI: asyncCompleteAPIProxy} } @@ -1925,6 +1940,9 @@ func AsyncGetExistingContentAPIProxy_Dispose(api *C.struct_Longtail_API) { // CreateAsyncPruneBlocksAPI ... func CreateAsyncPruneBlocksAPI(asyncComplete AsyncPruneBlocksAPI) Longtail_AsyncPruneBlocksAPI { cContext := SavePointer(asyncComplete) + if cContext == nil { + return Longtail_AsyncPruneBlocksAPI{} + } asyncCompleteAPIProxy := C.CreateAsyncPruneBlocksAPI(cContext) return Longtail_AsyncPruneBlocksAPI{cAsyncCompleteAPI: asyncCompleteAPIProxy} } @@ -1951,6 +1969,9 @@ func AsyncPruneBlocksAPIProxy_Dispose(api *C.struct_Longtail_API) { // CreateAsyncFlushAPI ... func CreateAsyncFlushAPI(asyncComplete AsyncFlushAPI) Longtail_AsyncFlushAPI { cContext := SavePointer(asyncComplete) + if cContext == nil { + return Longtail_AsyncFlushAPI{} + } asyncCompleteAPIProxy := C.CreateAsyncFlushAPI(cContext) return Longtail_AsyncFlushAPI{cAsyncCompleteAPI: asyncCompleteAPIProxy} } @@ -2275,6 +2296,9 @@ func BlockStoreAPIProxy_Flush(api *C.struct_Longtail_BlockStoreAPI, async_comple func CreateBlockStoreAPI(blockStore BlockStoreAPI) Longtail_BlockStoreAPI { cContext := SavePointer(blockStore) + if cContext == nil { + return Longtail_BlockStoreAPI{} + } blockStoreAPIProxy := C.CreateBlockStoreProxyAPI(cContext) return Longtail_BlockStoreAPI{cBlockStoreAPI: blockStoreAPIProxy} } @@ -2289,6 +2313,9 @@ func getLoggerFunc(logger Logger) C.Longtail_Log { //SetLogger ... func SetLogger(logger Logger) { cLoggerContext := SavePointer(logger) + if cLoggerContext == nil { + return + } C.Longtail_SetLog(getLoggerFunc(logger), cLoggerContext) }