private void ThreadStart(object parameter) { var tcs = (TaskCompletionSource <int>)parameter; try { _loop.Init(_engine.Libuv); _post.Init(_loop, OnPost); tcs.SetResult(0); } catch (Exception ex) { tcs.SetException(ex); return; } _initCompleted = true; try { var ran1 = _loop.Run(); if (_stopImmediate) { // thread-abort form of exit, resources will be leaked return; } // run the loop one more time to delete the open handles _post.Reference(); _post.Dispose(); _engine.Libuv.walk( _loop, (ptr, arg) => { var handle = UvMemory.FromIntPtr <UvHandle>(ptr); if (handle != _post) { handle.Dispose(); } }, IntPtr.Zero); // Ensure the Dispose operations complete in the event loop. var ran2 = _loop.Run(); _loop.Dispose(); } catch (Exception ex) { _closeError = ExceptionDispatchInfo.Capture(ex); // Request shutdown so we can rethrow this exception // in Stop which should be observable. _appLifetime.StopApplication(); } }
private void OnStopRude() { Walk(ptr => { var handle = UvMemory.FromIntPtr <UvHandle>(ptr); if (handle != _post) { // handle can be null because UvMemory.FromIntPtr looks up a weak reference handle?.Dispose(); } }); }
private void OnStopRude() { _engine.Libuv.walk( _loop, (ptr, arg) => { var handle = UvMemory.FromIntPtr <UvHandle>(ptr); if (handle != _post) { handle.Dispose(); } }, IntPtr.Zero); }
private void OnStopRude() { Walk(ptr => { var handle = UvMemory.FromIntPtr <UvHandle>(ptr); if (handle != _post) { handle.Dispose(); } }); // uv_unref is idempotent so it's OK to call this here and in AllowStop. _post.Unreference(); }
private void OnStopRude() { Walk(ptr => { var handle = UvMemory.FromIntPtr <UvHandle>(ptr); if (handle != _post) { // handle can be null because UvMemory.FromIntPtr looks up a weak reference handle?.Dispose(); } }); // uv_unref is idempotent so it's OK to call this here and in AllowStop. _post.Unreference(); }
/// <summary> /// Closes the connections. /// This must be called on the libuv event loop /// </summary> public void WalkConnectionsAndClose() { lock (this.ConnectionStopTasks) { EventThread.Walk(ptr => { var handle = UvMemory.FromIntPtr <UvHandle>(ptr); var connection = (handle as UvStreamHandle)?.Connection; if (connection != null) { ConnectionStopTasks.Add(connection.StopAsync()); } }); } }
private void ThreadStart(object parameter) { var tcs = (TaskCompletionSource <int>)parameter; try { _loop.Init(_engine.Libuv); _post.Init(_loop, OnPost); tcs.SetResult(0); } catch (Exception ex) { tcs.SetException(ex); } try { var ran1 = _loop.Run(); if (_stopImmediate) { // thread-abort form of exit, resources will be leaked return; } // run the loop one more time to delete the open handles _post.Reference(); _post.DangerousClose(); _engine.Libuv.walk( _loop, (ptr, arg) => { var handle = UvMemory.FromIntPtr <UvHandle>(ptr); handle.Dispose(); }, IntPtr.Zero); var ran2 = _loop.Run(); _loop.Dispose(); } catch (Exception ex) { _closeError = ExceptionDispatchInfo.Capture(ex); } }
// This must be called on the libuv event loop public void WalkConnectionsAndClose() { if (_connectionStopTasks != null) { throw new InvalidOperationException($"{nameof(WalkConnectionsAndClose)} cannot be called twice."); } _connectionStopTasks = new List <Task>(); _thread.Walk(ptr => { var handle = UvMemory.FromIntPtr <UvHandle>(ptr); var connection = (handle as UvStreamHandle)?.Connection; if (connection != null) { _connectionStopTasks.Add(connection.StopAsync()); } }); }
private void WalkConnectionsAndCloseCore(TaskCompletionSource <object> tcs) { var connectionStopTasks = new List <Task>(); _thread.Walk(ptr => { var handle = UvMemory.FromIntPtr <UvHandle>(ptr); var connection = (handle as UvStreamHandle)?.Connection; if (connection != null) { connectionStopTasks.Add(connection.StopAsync()); } }); _threadPool.Run(() => { Task.WaitAll(connectionStopTasks.ToArray()); tcs.SetResult(null); }); }
private void ThreadStart(object parameter) { lock (_startSync) { var tcs = (TaskCompletionSource <int>)parameter; try { _loop.Init(_libuv); _post.Init(_loop, OnPost, EnqueueCloseHandle); _initCompleted = true; tcs.SetResult(0); } catch (Exception ex) { tcs.SetException(ex); return; } } try { _loop.Run(); if (_stopImmediate) { // thread-abort form of exit, resources will be leaked return; } // run the loop one more time to delete the open handles _post.Reference(); _post.Dispose(); // We need this walk because we call ReadStop on accepted connections when there's back pressure // Calling ReadStop makes the handle as in-active which means the loop can // end while there's still valid handles around. This makes loop.Dispose throw // with an EBUSY. To avoid that, we walk all of the handles and dispose them. Walk(ptr => { var handle = UvMemory.FromIntPtr <UvHandle>(ptr); // handle can be null because UvMemory.FromIntPtr looks up a weak reference handle?.Dispose(); }); // Ensure the Dispose operations complete in the event loop. _loop.Run(); _loop.Dispose(); } catch (Exception ex) { _closeError = ex; // Request shutdown so we can rethrow this exception // in Stop which should be observable. _appLifetime.StopApplication(); } finally { try { MemoryPool.Dispose(); } catch (Exception ex) { _closeError = _closeError == null ? ex : new AggregateException(_closeError, ex); } WriteReqPool.Dispose(); _threadTcs.SetResult(null); #if DEBUG && !INNER_LOOP // Check for handle leaks after disposing everything CheckUvReqLeaks(); #endif } }