Background thread throws exception when unloading in AppDomain, how can I stop it? Error while uploading appdomain (HRESULT 0x80131015)

1

I've been using this program.

I am currently running the server program in an appdomain. However, when I want to unload it, it returns an exception with HRESULT 0x80131015. This only occurs when I start the pipeServer by clicking the button. I've checked which threads are running and tried to abort them, but they just won't abort. Their status comes back as "abort requested."

  public void Start(string pipename)
        {
            PipeName = pipename;

            //start the listening thread
            listenThread = new Thread(ListenForClients)
                               {
                                   IsBackground = true
                               };

            listenThread.Start();

            Running = true;
        }

        void ListenForClients()
        {
            SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR();

            // set the Security Descriptor to be completely permissive
            InitializeSecurityDescriptor(ref sd, SECURITY_DESCRIPTOR_REVISION);
            SetSecurityDescriptorDacl(ref sd, true, IntPtr.Zero, false);

            IntPtr ptrSD = Marshal.AllocCoTaskMem(Marshal.SizeOf(sd));
            Marshal.StructureToPtr(sd, ptrSD, false);

            SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES
                                         {
                                             nLength = Marshal.SizeOf(sd),
                                             lpSecurityDescriptor = ptrSD,
                                             bInheritHandle = 1
                                         };

            IntPtr ptrSA = Marshal.AllocCoTaskMem(Marshal.SizeOf(sa));
            Marshal.StructureToPtr(sa, ptrSA, false);


            while (true)
            {
                // Creates an instance of a named pipe for one client
                SafeFileHandle clientHandle =
                    CreateNamedPipe(
                        PipeName,

                        // DUPLEX | FILE_FLAG_OVERLAPPED = 0x00000003 | 0x40000000;
                        0x40000003,
                        0,
                        255,
                        BUFFER_SIZE,
                        BUFFER_SIZE,
                        0,
                        ptrSA);

                //could not create named pipe instance
                if (clientHandle.IsInvalid)
                    continue;

                int success = ConnectNamedPipe(clientHandle, IntPtr.Zero);

                //could not connect client
                if (success == 0)
                {
                    // close the handle, and wait for the next client
                    clientHandle.Close();
                    continue;
                }

                Client client = new Client
                                    {
                                        handle = clientHandle
                                    };

                lock (clients)
                    clients.Add(client);

                Thread readThread = new Thread(Read)
                                        {
                                            IsBackground = true
                                        };
                readThread.Start(client);
            }

            // free up the ptrs (never reached due to infinite loop)
            Marshal.FreeCoTaskMem(ptrSD);
            Marshal.FreeCoTaskMem(ptrSA);
        }

        void Read(object clientObj)
        {
            Client client = (Client)clientObj;
            client.stream = new FileStream(client.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
            byte[] buffer = new byte[BUFFER_SIZE];

            while (true)
            {
                int bytesRead = 0;

                using (MemoryStream ms = new MemoryStream())
                {
                    try
                    {
                        // read the total stream length
                        int totalSize = client.stream.Read(buffer, 0, 4);

                        // client has disconnected
                        if (totalSize == 0)
                            break;

                        totalSize = BitConverter.ToInt32(buffer, 0);

                        do
                        {
                            int numBytes = client.stream.Read(buffer, 0, Math.Min(totalSize - bytesRead, BUFFER_SIZE));

                            ms.Write(buffer, 0, numBytes);

                            bytesRead += numBytes;

                        } while (bytesRead < totalSize);

                    }
                    catch
                    {
                        //read error has occurred
                        break;
                    }

                    //client has disconnected
                    if (bytesRead == 0)
                        break;

                    //fire message received event
                    if (MessageReceived != null)

                        MessageReceived(ms.ToArray());
                }
            }

            // the clients must be locked - otherwise "stream.Close()"
            // could be called while SendMessage(byte[]) is being called on another thread.
            // This leads to an IO error & several wasted days.
            lock (clients)
            {
                //clean up resources
                DisconnectNamedPipe(client.handle);
                client.stream.Close();
                client.handle.Close();

                clients.Remove(client);
            }

            // invoke the event, a client disconnected
            if (ClientDisconnected != null)
                ClientDisconnected();
        }

This is some sample code which runs the two background threads. Any help on how to unload the appdomain safely?

multithreading
background
appdomain
hresult
asked on Stack Overflow May 20, 2014 by IamACatBug • edited May 20, 2014 by tshepang

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0