| Index: third_party/mojo/src/mojo/public/go/system/handle.go
|
| diff --git a/third_party/mojo/src/mojo/public/go/system/handle.go b/third_party/mojo/src/mojo/public/go/system/handle.go
|
| index 189c8dd15c030f3ec287cd9e331052135a61713b..d8d66dba4b30c2f34557c4b6c70486ff4f7ebc49 100644
|
| --- a/third_party/mojo/src/mojo/public/go/system/handle.go
|
| +++ b/third_party/mojo/src/mojo/public/go/system/handle.go
|
| @@ -4,9 +4,10 @@
|
|
|
| package system
|
|
|
| -//#include "c_allocators.h"
|
| -//#include "mojo/public/c/system/core.h"
|
| -import "C"
|
| +import (
|
| + "log"
|
| + "runtime"
|
| +)
|
|
|
| // Handle is a generic handle for mojo objects.
|
| type Handle interface {
|
| @@ -60,6 +61,30 @@ type UntypedHandle interface {
|
| ToSharedBufferHandle() SharedBufferHandle
|
| }
|
|
|
| +// finalizeHandle closes handles that becomes unreachable in runtime.
|
| +// We want to make sure that every mojo handle is closed, so we set this
|
| +// finalizer function on every handle object we create. If a handle object
|
| +// becomes invalidated (because the handle was closed or the underlying mojo
|
| +// handle has been passed to another handle object), we remove the finalizer.
|
| +//
|
| +// The finalizing mechanism works tricky: runtime.SetFinalizer can be called on
|
| +// an object allocated by calling new or by taking the address of a composite
|
| +// literal, so we can't set a finalizer on an embedded struct if the embedded
|
| +// struct has a non-zero offset related to the outmost struct.
|
| +//
|
| +// Type structure of handles is the following: there is a struct baseHandle,
|
| +// which serves as a "base class" for all the typed handles (i.e. sharedBuffer,
|
| +// untypedHandleImpl, dataPipeProducer, dataPipeConsumer and messagePipe). We
|
| +// express it by struct embedding. When we operate with handles, we create typed
|
| +// handles and set finalizers on them, while to invalidate a handle and remove
|
| +// finalizer we call methods on the embedded baseHandle struct. So in order for
|
| +// finalizers to work correct we need to make sure that baseHandle is the first
|
| +// component of typed handles.
|
| +func finalizeHandle(h Handle) {
|
| + log.Println("Handle was not closed.")
|
| + h.Close()
|
| +}
|
| +
|
| type baseHandle struct {
|
| core *coreImpl
|
| mojoHandle MojoHandle
|
| @@ -67,15 +92,16 @@ type baseHandle struct {
|
|
|
| func (h *baseHandle) invalidate() {
|
| h.mojoHandle = MOJO_HANDLE_INVALID
|
| + runtime.SetFinalizer(h, nil)
|
| }
|
|
|
| func (h *baseHandle) Close() MojoResult {
|
| - h.core.mu.Lock()
|
| - defer h.core.mu.Unlock()
|
| -
|
| mojoHandle := h.mojoHandle
|
| h.invalidate()
|
| - return MojoResult(C.MojoClose(mojoHandle.cValue()))
|
| + h.core.mu.Lock()
|
| + r := sysImpl.Close(uint32(mojoHandle))
|
| + h.core.mu.Unlock()
|
| + return MojoResult(r)
|
| }
|
|
|
| func (h *baseHandle) IsValid() bool {
|
| @@ -94,42 +120,50 @@ func (h *baseHandle) ReleaseNativeHandle() MojoHandle {
|
|
|
| func (h *baseHandle) ToUntypedHandle() UntypedHandle {
|
| handle := &untypedHandleImpl{*h}
|
| + runtime.SetFinalizer(handle, finalizeHandle)
|
| h.invalidate()
|
| return handle
|
| }
|
|
|
| func (h *baseHandle) Wait(signals MojoHandleSignals, deadline MojoDeadline) (MojoResult, MojoHandleSignalsState) {
|
| - cParams := C.MallocWaitParams()
|
| - defer C.FreeWaitParams(cParams)
|
| - *cParams.state = C.struct_MojoHandleSignalsState{}
|
| - result := C.MojoWait(h.mojoHandle.cValue(), signals.cValue(), deadline.cValue(), cParams.state)
|
| - return MojoResult(result), cParams.state.goValue()
|
| + r, satisfiedSignals, satisfiableSignals := sysImpl.Wait(uint32(h.mojoHandle), uint32(signals), uint64(deadline))
|
| + state := MojoHandleSignalsState{
|
| + SatisfiedSignals: MojoHandleSignals(satisfiedSignals),
|
| + SatisfiableSignals: MojoHandleSignals(satisfiableSignals),
|
| + }
|
| + return MojoResult(r), state
|
| }
|
|
|
| type untypedHandleImpl struct {
|
| + // baseHandle should always be the first component of this struct,
|
| + // see |finalizeHandle()| for more details.
|
| baseHandle
|
| }
|
|
|
| func (h *untypedHandleImpl) ToConsumerHandle() ConsumerHandle {
|
| handle := &dataPipeConsumer{h.baseHandle}
|
| + runtime.SetFinalizer(handle, finalizeHandle)
|
| h.invalidate()
|
| return handle
|
| }
|
|
|
| func (h *untypedHandleImpl) ToProducerHandle() ProducerHandle {
|
| handle := &dataPipeProducer{h.baseHandle}
|
| + runtime.SetFinalizer(handle, finalizeHandle)
|
| h.invalidate()
|
| return handle
|
| }
|
|
|
| func (h *untypedHandleImpl) ToMessagePipeHandle() MessagePipeHandle {
|
| handle := &messagePipe{h.baseHandle}
|
| + runtime.SetFinalizer(handle, finalizeHandle)
|
| h.invalidate()
|
| return handle
|
| }
|
|
|
| func (h *untypedHandleImpl) ToSharedBufferHandle() SharedBufferHandle {
|
| handle := &sharedBuffer{h.baseHandle}
|
| + runtime.SetFinalizer(handle, finalizeHandle)
|
| h.invalidate()
|
| return handle
|
| }
|
|
|