fix: wrap libopusfile init call for go test -race

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
This commit is contained in:
Hraban Luyat 2020-07-10 09:37:18 +01:00
parent f08db0e111
commit 2a2b57e79d
2 changed files with 15 additions and 7 deletions

View 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);
}

View file

@ -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)
}