Example #1
0
        protected override bool ReleaseHandle()
        {
            int error = 0;

            Socket.Blocking_internal(handle, false, out error);
#if MOBILE_STATIC
            /* 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)
                            {
                                throw new Exception("Could not abort registered blocking threads before closing socket.");
                            }

                            // 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);
        }
Example #2
0
        protected override bool ReleaseHandle()
        {
            int error = 0;

            Socket.Blocking_internal(handle, false, out error);

            if (blocking_threads != null)
            {
                int abort_attempts = 0;
                while (blocking_threads.Count > 0)
                {
                    if (abort_attempts++ >= ABORT_RETRIES)
                    {
                        if (THROW_ON_ABORT_RETRIES)
                        {
                            throw new Exception("Could not abort registered blocking threads before closing socket.");
                        }

                        // 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.
                     */
                    lock (blocking_threads) {
                        if (blocking_threads.Count == 1 && blocking_threads[0] == Thread.CurrentThread)
                        {
                            break;
                        }
                    }

                    AbortRegisteredThreads();
                    // Sleep so other threads can resume
                    Thread.Sleep(1);
                }
            }

            Socket.Close_internal(handle, out error);

            return(error == 0);
        }