System.Net.Sockets.SafeSocketHandle.ReleaseHandle C# (CSharp) Method

ReleaseHandle() protected method

protected ReleaseHandle ( ) : bool
return bool
		protected override bool ReleaseHandle ()
		{
			int error = 0;

			Socket.Blocking_internal (handle, false, out error);
#if FULL_AOT_DESKTOP
			/* It's only for platforms that do not have working syscall abort mechanism, like WatchOS and TvOS */
			Socket.Shutdown_internal (handle, SocketShutdown.Both, out error);
#endif

			if (blocking_threads != null) {
				lock (blocking_threads) {
					int abort_attempts = 0;
					while (blocking_threads.Count > 0) {
						if (abort_attempts++ >= ABORT_RETRIES) {
							if (THROW_ON_ABORT_RETRIES) {
								StringBuilder sb = new StringBuilder ();
								sb.AppendLine ("Could not abort registered blocking threads before closing socket.");
								foreach (var thread in blocking_threads) {
									sb.AppendLine ("Thread StackTrace:");
									sb.AppendLine (threads_stacktraces[thread].ToString ());
								}
								sb.AppendLine ();

								throw new Exception (sb.ToString ());
							}

							// Attempts to close the socket safely failed.
							// We give up, and close the socket with pending blocking system calls.
							// This should not occur, nonetheless if it does this avoids an endless loop.
							break;
						}

						/*
						* This method can be called by the DangerousRelease inside RegisterForBlockingSyscall
						* When this happens blocking_threads contains the current thread.
						* We can safely close the socket and throw SocketException in RegisterForBlockingSyscall
						* before the blocking system call.
						*/
						if (blocking_threads.Count == 1 && blocking_threads[0] == Thread.CurrentThread)
							break;

						// abort registered threads
						foreach (var t in blocking_threads)
							Socket.cancel_blocking_socket_operation (t);

						// Sleep so other threads can resume
						in_cleanup = true;
						Monitor.Wait (blocking_threads, 100);
					}
				}
			}

			Socket.Close_internal (handle, out error);

			return error == 0;
		}