static void OnCloseHandle(IntPtr handle) { if (handle == IntPtr.Zero) { return; } ScheduleHandle scheduleHandle = null; // Get gc handle first IntPtr pHandle = ((uv_handle_t *)handle)->data; if (pHandle != IntPtr.Zero) { GCHandle nativeHandle = GCHandle.FromIntPtr(pHandle); if (nativeHandle.IsAllocated) { scheduleHandle = nativeHandle.Target as ScheduleHandle; nativeHandle.Free(); ((uv_handle_t *)handle)->data = IntPtr.Zero; Log.TraceFormat("{0} {1} GCHandle released.", scheduleHandle?.HandleType, handle); } } // Release memory Marshal.FreeHGlobal(handle); scheduleHandle?.OnHandleClosed(); Log.InfoFormat("{0} {1} memory and GCHandle released.", scheduleHandle?.HandleType, handle); }
internal HandleContext( uv_handle_type handleType, Func <IntPtr, IntPtr, object[], int> initializer, IntPtr loopHandle, ScheduleHandle target, params object[] args) { Contract.Requires(loopHandle != IntPtr.Zero); Contract.Requires(initializer != null); Contract.Requires(target != null); int size = NativeMethods.GetSize(handleType); IntPtr handle = Marshal.AllocHGlobal(size); int result; try { result = initializer(loopHandle, handle, args); } catch (Exception) { Marshal.FreeHGlobal(handle); throw; } if (result < 0) { Marshal.FreeHGlobal(handle); throw NativeMethods.CreateError((uv_err_code)result); } GCHandle gcHandle = GCHandle.Alloc(target, GCHandleType.Normal); ((uv_handle_t *)handle)->data = GCHandle.ToIntPtr(gcHandle); this.Handle = handle; this.handleType = handleType; if (Log.IsInfoEnabled) { Log.InfoFormat("{0} {1} allocated.", handleType, handle); } }