]> Sergey Matveev's repositories - go-opus.git/commitdiff
fix: wrap libopusfile init call for go test -race
authorHraban Luyat <hraban@0brg.net>
Fri, 10 Jul 2020 08:37:18 +0000 (09:37 +0100)
committerHraban Luyat <hraban@0brg.net>
Fri, 10 Jul 2020 08:40:35 +0000 (09:40 +0100)
Since go 1.14 the race checker includes an overzealous pointer checker.
It marks all conversions from uintptr to unsafe.Pointer as an error, but
in reality that's allowed as long as you never dereference the pointer
or do any arithmetic on it. The C compiler doesn't complain about this,
so we pass the uintptr value to C and convert it there, in a small
wrapper function.

See https://groups.google.com/g/golang-nuts/c/995uZyRPKlU for more
details.

Fixes hraban/opus#28

callbacks.c
stream.go

index caa7c0dafce4b5902d7ec12611a26160981cc302..5645f30ddfee04b5ee6be70ab1a79834cf311cc8 100644 (file)
@@ -6,6 +6,7 @@
 // plays nice with the CGo rules and avoids any confusion.
 
 #include <opusfile.h>
+#include <stdint.h>
 
 // Defined in Go. Uses the same signature as Go, no need for proxy function.
 int go_readcallback(void *p, unsigned char *buf, int nbytes);
@@ -15,3 +16,14 @@ int go_readcallback(void *p, unsigned char *buf, int nbytes);
 struct OpusFileCallbacks callbacks = {
     .read = go_readcallback,
 };
+
+// Proxy function for op_open_callbacks, because it takes a void * context but
+// we want to pass it non-pointer data, namely an arbitrary uintptr_t
+// value. This is legal C, but go test -race (-d=checkptr) complains anyway. So
+// we have this wrapper function to shush it.
+// https://groups.google.com/g/golang-nuts/c/995uZyRPKlU
+OggOpusFile *
+my_open_callbacks(uintptr_t p, const OpusFileCallbacks *cb, int *error)
+{
+    return op_open_callbacks((void *)p, cb, NULL, 0, error);
+}
index 208a0bc9d5562d748365f6a08014ef630a423734..60f99e0ad515537a8d3684fcef9b088c5f6c7d6e 100644 (file)
--- a/stream.go
+++ b/stream.go
@@ -13,9 +13,11 @@ import (
 /*
 #cgo pkg-config: opusfile
 #include <opusfile.h>
+#include <stdint.h>
 #include <string.h>
 
 extern struct OpusFileCallbacks callbacks;
+OggOpusFile *my_open_callbacks(uintptr_t p, const OpusFileCallbacks *cb, int *error);
 
 */
 import "C"
@@ -103,13 +105,7 @@ func (s *Stream) Init(read io.Reader) error {
        // called.
        streams.Save(s)
        defer streams.Del(s)
-       oggfile := C.op_open_callbacks(
-               // "C code may not keep a copy of a Go pointer after the call returns."
-               unsafe.Pointer(s.id),
-               &C.callbacks,
-               nil,
-               0,
-               &errno)
+       oggfile := C.my_open_callbacks(C.uintptr_t(s.id), &C.callbacks, &errno)
        if errno != 0 {
                return StreamError(errno)
        }