Skip to content

Commit

Permalink
Fix violation of cgo pointer rules
Browse files Browse the repository at this point in the history
  • Loading branch information
mpoindexter committed Aug 15, 2023
1 parent 0ece357 commit fe5e551
Show file tree
Hide file tree
Showing 16 changed files with 120 additions and 121 deletions.
10 changes: 5 additions & 5 deletions shared_directory_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ const (
)

//export linuxInstallRosettaWithCompletionHandler
func linuxInstallRosettaWithCompletionHandler(cgoHandlerPtr, errPtr unsafe.Pointer) {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
func linuxInstallRosettaWithCompletionHandler(cgoHandleUintptr C.uintptr_t, errPtr unsafe.Pointer) {
cgoHandle := cgo.Handle(cgoHandleUintptr)

handler := cgoHandler.Value().(func(error))
handler := cgoHandle.Value().(func(error))

if err := newNSError(errPtr); err != nil {
handler(err)
Expand Down Expand Up @@ -89,10 +89,10 @@ func LinuxRosettaDirectoryShareInstallRosetta() error {
return err
}
errCh := make(chan error, 1)
cgoHandler := cgo.NewHandle(func(err error) {
cgoHandle := cgo.NewHandle(func(err error) {
errCh <- err
})
C.linuxInstallRosetta(unsafe.Pointer(&cgoHandler))
C.linuxInstallRosetta(C.uintptr_t(cgoHandle))
return <-errCh
}

Expand Down
28 changes: 14 additions & 14 deletions socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,17 +97,17 @@ func (v *VirtioSocketDevice) Listen(port uint32) (*VirtioSocketListener, error)

ch := make(chan connResults, 1) // should I increase more caps?

handler := cgo.NewHandle(func(conn *VirtioSocketConnection, err error) {
handle := cgo.NewHandle(func(conn *VirtioSocketConnection, err error) {
ch <- connResults{conn, err}
})
ptr := C.newVZVirtioSocketListener(
unsafe.Pointer(&handler),
C.uintptr_t(handle),
)
listener := &VirtioSocketListener{
pointer: objc.NewPointer(ptr),
vsockDevice: v,
port: port,
handler: handler,
handle: handle,
acceptch: ch,
}

Expand All @@ -122,10 +122,10 @@ func (v *VirtioSocketDevice) Listen(port uint32) (*VirtioSocketListener, error)
}

//export connectionHandler
func connectionHandler(connPtr, errPtr, cgoHandlerPtr unsafe.Pointer) {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
handler := cgoHandler.Value().(func(*VirtioSocketConnection, error))
defer cgoHandler.Delete()
func connectionHandler(connPtr, errPtr unsafe.Pointer, cgoHandleUintptr C.uintptr_t) {
cgoHandle := cgo.Handle(cgoHandleUintptr)
handler := cgoHandle.Value().(func(*VirtioSocketConnection, error))
defer cgoHandle.Delete()
// see: startHandler
if err := newNSError(errPtr); err != nil {
handler(nil, err)
Expand All @@ -144,15 +144,15 @@ func connectionHandler(connPtr, errPtr, cgoHandlerPtr unsafe.Pointer) {
// see: https://developer.apple.com/documentation/virtualization/vzvirtiosocketdevice/3656677-connecttoport?language=objc
func (v *VirtioSocketDevice) Connect(port uint32) (*VirtioSocketConnection, error) {
ch := make(chan connResults, 1)
cgoHandler := cgo.NewHandle(func(conn *VirtioSocketConnection, err error) {
cgoHandle := cgo.NewHandle(func(conn *VirtioSocketConnection, err error) {
ch <- connResults{conn, err}
close(ch)
})
C.VZVirtioSocketDevice_connectToPort(
objc.Ptr(v),
v.dispatchQueue,
C.uint32_t(port),
unsafe.Pointer(&cgoHandler),
C.uintptr_t(cgoHandle),
)
result := <-ch
runtime.KeepAlive(v)
Expand All @@ -170,7 +170,7 @@ type connResults struct {
type VirtioSocketListener struct {
*pointer
vsockDevice *VirtioSocketDevice
handler cgo.Handle
handle cgo.Handle
port uint32
acceptch chan connResults
closeOnce sync.Once
Expand All @@ -197,7 +197,7 @@ func (v *VirtioSocketListener) Close() error {
v.vsockDevice.dispatchQueue,
C.uint32_t(v.port),
)
v.handler.Delete()
v.handle.Delete()
})
return nil
}
Expand Down Expand Up @@ -226,9 +226,9 @@ func (a *VirtioSocketListenerAddr) Network() string { return "vsock" }
func (a *VirtioSocketListenerAddr) String() string { return fmt.Sprintf("%d:%d", a.CID, a.Port) }

//export shouldAcceptNewConnectionHandler
func shouldAcceptNewConnectionHandler(cgoHandlerPtr, connPtr, devicePtr unsafe.Pointer) C.bool {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
handler := cgoHandler.Value().(func(*VirtioSocketConnection, error))
func shouldAcceptNewConnectionHandler(cgoHandleUintptr C.uintptr_t, connPtr, devicePtr unsafe.Pointer) C.bool {
cgoHandle := cgo.Handle(cgoHandleUintptr)
handler := cgoHandle.Value().(func(*VirtioSocketConnection, error))

// see: startHandler
conn, err := newVirtioSocketConnection(connPtr)
Expand Down
62 changes: 31 additions & 31 deletions virtualization.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ type VirtualMachine struct {

*pointer
dispatchQueue unsafe.Pointer
stateHandle *machineState
machineState *machineState

finalizeOnce sync.Once
}
Expand Down Expand Up @@ -103,28 +103,28 @@ func NewVirtualMachine(config *VirtualMachineConfiguration) (*VirtualMachine, er
cs := (*char)(objc.GetUUID())
dispatchQueue := C.makeDispatchQueue(cs.CString())

stateHandle := &machineState{
machineState := &machineState{
state: VirtualMachineState(0),
stateNotify: infinity.NewChannel[VirtualMachineState](),
}

stateHandlePtr := cgo.NewHandle(stateHandle)
stateHandle := cgo.NewHandle(machineState)
v := &VirtualMachine{
id: cs.String(),
pointer: objc.NewPointer(
C.newVZVirtualMachineWithDispatchQueue(
objc.Ptr(config),
dispatchQueue,
unsafe.Pointer(&stateHandlePtr),
C.uintptr_t(stateHandle),
),
),
dispatchQueue: dispatchQueue,
stateHandle: stateHandle,
machineState: machineState,
}

objc.SetFinalizer(v, func(self *VirtualMachine) {
self.finalize()
stateHandlePtr.Delete()
stateHandle.Delete()
})
return v, nil
}
Expand Down Expand Up @@ -155,11 +155,11 @@ func (v *VirtualMachine) SocketDevices() []*VirtioSocketDevice {
}

//export changeStateOnObserver
func changeStateOnObserver(newStateRaw C.int, cgoHandlerPtr unsafe.Pointer) {
stateHandler := *(*cgo.Handle)(cgoHandlerPtr)
func changeStateOnObserver(newStateRaw C.int, cgoHandleUintptr C.uintptr_t) {
stateHandle := cgo.Handle(cgoHandleUintptr)
// I expected it will not cause panic.
// if caused panic, that's unexpected behavior.
v, _ := stateHandler.Value().(*machineState)
v, _ := stateHandle.Value().(*machineState)
v.mu.Lock()
newState := VirtualMachineState(newStateRaw)
v.state = newState
Expand All @@ -169,16 +169,16 @@ func changeStateOnObserver(newStateRaw C.int, cgoHandlerPtr unsafe.Pointer) {

// State represents execution state of the virtual machine.
func (v *VirtualMachine) State() VirtualMachineState {
v.stateHandle.mu.RLock()
defer v.stateHandle.mu.RUnlock()
return v.stateHandle.state
v.machineState.mu.RLock()
defer v.machineState.mu.RUnlock()
return v.machineState.state
}

// StateChangedNotify gets notification is changed execution state of the virtual machine.
func (v *VirtualMachine) StateChangedNotify() <-chan VirtualMachineState {
v.stateHandle.mu.RLock()
defer v.stateHandle.mu.RUnlock()
return v.stateHandle.stateNotify.Out()
v.machineState.mu.RLock()
defer v.machineState.mu.RUnlock()
return v.machineState.stateNotify.Out()
}

// CanStart returns true if the machine is in a state that can be started.
Expand Down Expand Up @@ -213,10 +213,10 @@ func (v *VirtualMachine) CanStop() bool {
}

//export virtualMachineCompletionHandler
func virtualMachineCompletionHandler(cgoHandlerPtr, errPtr unsafe.Pointer) {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
func virtualMachineCompletionHandler(cgoHandleUintptr C.uintptr_t, errPtr unsafe.Pointer) {
cgoHandle := cgo.Handle(cgoHandleUintptr)

handler := cgoHandler.Value().(func(error))
handler := cgoHandle.Value().(func(error))

if err := newNSError(errPtr); err != nil {
handler(err)
Expand Down Expand Up @@ -255,18 +255,18 @@ func (v *VirtualMachine) Start(opts ...VirtualMachineStartOption) error {
}

h, errCh := makeHandler()
handler := cgo.NewHandle(h)
defer handler.Delete()
handle := cgo.NewHandle(h)
defer handle.Delete()

if o.macOSVirtualMachineStartOptionsPtr != nil {
C.startWithOptionsCompletionHandler(
objc.Ptr(v),
v.dispatchQueue,
o.macOSVirtualMachineStartOptionsPtr,
unsafe.Pointer(&handler),
C.uintptr_t(handle),
)
} else {
C.startWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, unsafe.Pointer(&handler))
C.startWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, C.uintptr_t(handle))
}
return <-errCh
}
Expand All @@ -276,9 +276,9 @@ func (v *VirtualMachine) Start(opts ...VirtualMachineStartOption) error {
// If you want to listen status change events, use the "StateChangedNotify" method.
func (v *VirtualMachine) Pause() error {
h, errCh := makeHandler()
handler := cgo.NewHandle(h)
defer handler.Delete()
C.pauseWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, unsafe.Pointer(&handler))
handle := cgo.NewHandle(h)
defer handle.Delete()
C.pauseWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, C.uintptr_t(handle))
return <-errCh
}

Expand All @@ -287,9 +287,9 @@ func (v *VirtualMachine) Pause() error {
// If you want to listen status change events, use the "StateChangedNotify" method.
func (v *VirtualMachine) Resume() error {
h, errCh := makeHandler()
handler := cgo.NewHandle(h)
defer handler.Delete()
C.resumeWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, unsafe.Pointer(&handler))
handle := cgo.NewHandle(h)
defer handle.Delete()
C.resumeWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, C.uintptr_t(handle))
return <-errCh
}

Expand Down Expand Up @@ -322,9 +322,9 @@ func (v *VirtualMachine) Stop() error {
return err
}
h, errCh := makeHandler()
handler := cgo.NewHandle(h)
defer handler.Delete()
C.stopWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, unsafe.Pointer(&handler))
handle := cgo.NewHandle(h)
defer handle.Delete()
C.stopWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, C.uintptr_t(handle))
return <-errCh
}

Expand Down
22 changes: 11 additions & 11 deletions virtualization_11.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
#import <Virtualization/Virtualization.h>

/* exported from cgo */
void connectionHandler(void *connection, void *err, void *cgoHandlerPtr);
void changeStateOnObserver(int state, void *cgoHandler);
bool shouldAcceptNewConnectionHandler(void *cgoHandler, void *connection, void *socketDevice);
void connectionHandler(void *connection, void *err, uintptr_t cgoHandle);
void changeStateOnObserver(int state, uintptr_t cgoHandle);
bool shouldAcceptNewConnectionHandler(uintptr_t cgoHandle, void *connection, void *socketDevice);

@interface Observer : NSObject
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
Expand All @@ -21,13 +21,13 @@ bool shouldAcceptNewConnectionHandler(void *cgoHandler, void *connection, void *
@interface ObservableVZVirtualMachine : VZVirtualMachine
- (instancetype)initWithConfiguration:(VZVirtualMachineConfiguration *)configuration
queue:(dispatch_queue_t)queue
statusHandler:(void *)statusHandler;
statusUpdateHandle:(uintptr_t)statusUpdateHandle;
- (void)dealloc;
@end

/* VZVirtioSocketListener */
@interface VZVirtioSocketListenerDelegateImpl : NSObject <VZVirtioSocketListenerDelegate>
- (instancetype)initWithHandler:(void *)cgoHandler;
- (instancetype)initWithHandle:(uintptr_t)cgoHandle;
- (BOOL)listener:(VZVirtioSocketListener *)listener shouldAcceptNewConnection:(VZVirtioSocketConnection *)connection fromSocketDevice:(VZVirtioSocketDevice *)socketDevice;
@end

Expand Down Expand Up @@ -77,18 +77,18 @@ void *newVZVirtioSocketDeviceConfiguration();
void *newVZMACAddress(const char *macAddress);
void *newRandomLocallyAdministeredVZMACAddress();
const char *getVZMACAddressString(void *macAddress);
void *newVZVirtioSocketListener(void *cgoHandlerPtr);
void *newVZVirtioSocketListener(uintptr_t cgoHandle);
void *VZVirtualMachine_socketDevices(void *machine);
void VZVirtioSocketDevice_setSocketListenerForPort(void *socketDevice, void *vmQueue, void *listener, uint32_t port);
void VZVirtioSocketDevice_removeSocketListenerForPort(void *socketDevice, void *vmQueue, uint32_t port);
void VZVirtioSocketDevice_connectToPort(void *socketDevice, void *vmQueue, uint32_t port, void *cgoHandlerPtr);
void VZVirtioSocketDevice_connectToPort(void *socketDevice, void *vmQueue, uint32_t port, uintptr_t cgoHandle);

/* VirtualMachine */
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, void *statusHandler);
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, uintptr_t cgoHandle);
bool requestStopVirtualMachine(void *machine, void *queue, void **error);
void startWithCompletionHandler(void *machine, void *queue, void *completionHandler);
void pauseWithCompletionHandler(void *machine, void *queue, void *completionHandler);
void resumeWithCompletionHandler(void *machine, void *queue, void *completionHandler);
void startWithCompletionHandler(void *machine, void *queue, uintptr_t cgoHandle);
void pauseWithCompletionHandler(void *machine, void *queue, uintptr_t cgoHandle);
void resumeWithCompletionHandler(void *machine, void *queue, uintptr_t cgoHandle);
bool vmCanStart(void *machine, void *queue);
bool vmCanPause(void *machine, void *queue);
bool vmCanResume(void *machine, void *queue);
Expand Down
Loading

0 comments on commit fe5e551

Please sign in to comment.