Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix violation of cgo pointer rules #135

Merged
merged 1 commit into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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