diff options
author | Alexander Demidenko <hurd@yandex-team.ru> | 2021-03-19 12:11:21 +0700 |
---|---|---|
committer | Alexander Demidenko <hurd@yandex-team.ru> | 2021-03-19 12:24:59 +0700 |
commit | 8ff6fc436ce5a5be694e7d4cc9e56ded10184d80 (patch) | |
tree | 9e0b6b8ead5d6a16c4e552e9185e8ac2423d4c88 | |
parent | 4e16c7100cc7f8dddca051ff393460d7a1a77c98 (diff) |
Fix panic during disconnection
Sometimes there are situations when the callback is called during the processing of the disconnect.
To avoid problems with races (for example, when using race-detector), use atomic pointers.
Signed-off-by: Alexander Demidenko <hurd@yandex-team.ru>
Change-Id: Ic825872ac620d68a191bc88889a096b15ea57464
-rw-r--r-- | adapter/vppapiclient/vppapiclient.go | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/adapter/vppapiclient/vppapiclient.go b/adapter/vppapiclient/vppapiclient.go index 977f32d..7297590 100644 --- a/adapter/vppapiclient/vppapiclient.go +++ b/adapter/vppapiclient/vppapiclient.go @@ -29,6 +29,7 @@ import ( "os" "path/filepath" "reflect" + "sync/atomic" "time" "unsafe" @@ -52,7 +53,7 @@ const ( // global VPP binary API client, library vppapiclient only supports // single connection at a time -var globalVppClient *vppClient +var globalVppClient unsafe.Pointer // stubVppClient is the default implementation of the VppAPI. type vppClient struct { @@ -76,7 +77,8 @@ func NewVppClientWithInputQueueSize(shmPrefix string, inputQueueSize uint16) ada // Connect connects the process to VPP. func (a *vppClient) Connect() error { - if globalVppClient != nil { + h := (*vppClient)(atomic.LoadPointer(&globalVppClient)) + if h != nil { return fmt.Errorf("already connected to binary API, disconnect first") } @@ -92,19 +94,17 @@ func (a *vppClient) Connect() error { return fmt.Errorf("connecting to VPP binary API failed (rc=%v)", rc) } - globalVppClient = a + atomic.StorePointer(&globalVppClient, unsafe.Pointer(a)) return nil } // Disconnect disconnects the process from VPP. func (a *vppClient) Disconnect() error { - globalVppClient = nil - + atomic.StorePointer(&globalVppClient, nil) rc := C.govpp_disconnect() if rc != 0 { return fmt.Errorf("disconnecting from VPP binary API failed (rc=%v)", rc) } - return nil } @@ -187,9 +187,12 @@ func (a *vppClient) WaitReady() error { //export go_msg_callback func go_msg_callback(msgID C.uint16_t, data unsafe.Pointer, size C.size_t) { + h := (*vppClient)(atomic.LoadPointer(&globalVppClient)) + if h == nil { + return + } // convert unsafe.Pointer to byte slice sliceHeader := &reflect.SliceHeader{Data: uintptr(data), Len: int(size), Cap: int(size)} byteSlice := *(*[]byte)(unsafe.Pointer(sliceHeader)) - - globalVppClient.msgCallback(uint16(msgID), byteSlice) + h.msgCallback(uint16(msgID), byteSlice) } |