WorkerProcess.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / SMSvcHost / System / ServiceModel / Activation / WorkerProcess.cs / 1 / WorkerProcess.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace System.ServiceModel.Activation 
{
    using System; 
    using System.Threading; 
    using System.Diagnostics;
    using System.ServiceModel; 
    using System.ServiceModel.Channels;
    using System.ServiceModel.Diagnostics;
    using System.ServiceModel.Activation.Diagnostics;
    using System.Globalization; 
    using System.Security.AccessControl;
    using System.Reflection; 
    using System.IO; 

    using StringTraceRecord = System.ServiceModel.Diagnostics.StringTraceRecord; 

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    abstract class WorkerProcess : IConnectionRegister
    { 
        int isUnregistered;
        int processId; 
        MessageQueue queue; 
        int queueId;
        IConnectionDuplicator connectionDuplicator; 

        public bool IsRegistered
        {
            get { return isUnregistered == 0; } 
        }
 
        public MessageQueue Queue 
        {
            get 
            {
                return this.queue;
            }
 
            set
            { 
                this.queue = value; 
            }
        } 

        public int ProcessId
        {
            get 
            {
                return this.processId; 
            } 
        }
 
#if DEBUG
        public int QueueId
        {
            get 
            {
                return this.queueId; 
            } 
        }
#endif 

        internal void Close()
        {
            if (Interlocked.Increment(ref isUnregistered) == 1) 
            {
                if (this.queue != null) 
                { 
                    this.queue.Unregister(this);
                } 
            }
        }

        protected abstract DuplicateContext DuplicateConnection(ListenerSessionConnection session); 
        protected abstract void OnDispatchSuccess();
        protected abstract TransportType TransportType { get; } 
 
        internal IAsyncResult BeginDispatchSession(ListenerSessionConnection session, AsyncCallback callback, object state)
        { 
            return new DispatchSessionAsyncResult(session, callback, state);
        }

        internal bool EndDispatchSession(IAsyncResult result) 
        {
            try 
            { 
                DispatchSessionAsyncResult dispatchAsyncResult = DispatchSessionAsyncResult.End(result);
                if (dispatchAsyncResult.DuplicateSucceeded) 
                {
                    OnDispatchSuccess();
                    return true;
                } 
            }
            catch (Exception exception) 
            { 
                EventLogEventId logEventId = EventLogEventId.MessageQueueDuplicatedSocketLeak;
                if (this.TransportType == TransportType.NamedPipe) 
                {
                    logEventId = EventLogEventId.MessageQueueDuplicatedPipeLeak;
                }
 
                Debug.Print("WorkerProcess.DispatchSession() failed sending duplicated socket to processId: " + this.ProcessId + " exception:" + exception);
                DiagnosticUtility.EventLog.LogEvent(TraceEventType.Error, 
                    EventLogCategory.SharingService, 
                    logEventId,
                    this.ProcessId.ToString(NumberFormatInfo.InvariantInfo), 
                    System.ServiceModel.Diagnostics.DiagnosticTrace.CreateSourceString(this),
                    exception.ToString());

                if (DiagnosticUtility.IsFatal(exception)) 
                {
                    throw; 
                } 

                Close(); 

                // make sure we close the connection to the SharedConnectionListener
                // so it knows we've unregistered it
                ((IChannel)connectionDuplicator).Abort(); 

                if (!ShouldRecoverFromProxyCall(exception)) 
                { 
                    throw;
                } 
            }

            return false;
        } 

        internal IConnectionDuplicator ConnectionDuplicator 
        { 
            get
            { 
                return this.connectionDuplicator;
            }
        }
 
        void WorkerProcess_Closed(object sender, EventArgs e)
        { 
            Debug.Print("WorkerProcess.WorkerProcess_Closed() worker leaving: " + processId + " State: " + ((IDuplexContextChannel)sender).State); 
            Close();
        } 

        void WorkerProcess_Faulted(object sender, EventArgs e)
        {
            Debug.Print("WorkerProcess.WorkerProcess_Faulted() worker leaving: " + processId + " State: " + ((IDuplexContextChannel)sender).State); 
            Close();
        } 
 
        ListenerExceptionStatus IConnectionRegister.Register(Version version, int processId, BaseUriWithWildcard path, int queueId, Guid token, string eventName)
        { 
            Debug.Print("WorkerProcess.Register() version: " + version + " processId: " + processId + " path: " + path + " queueId: " + queueId + " token: " + token + " eventName: " + eventName);

            if (DiagnosticUtility.ShouldTraceInformation)
            { 
                ListenerTraceUtility.TraceEvent(TraceEventType.Information, TraceCode.MessageQueueRegisterCalled, new StringTraceRecord("Path", path.ToString()), this, null);
            } 
 
            // Get the callback channel
            this.connectionDuplicator = OperationContext.Current.GetCallbackChannel(); 

            ListenerExceptionStatus status = ListenerExceptionStatus.Success;
            bool abortInstance = false;
 
            if (path == null || eventName == null)
            { 
                status = ListenerExceptionStatus.InvalidArgument; 
                abortInstance = true;
                goto FAILED; 
            }

            // Vista only: validate remote process ID
            if (OSEnvironmentHelper.IsVistaOrGreater) 
            {
                status = ListenerExceptionStatus.InvalidArgument; 
                object property = OperationContext.Current.IncomingMessage.Properties[ConnectionMessageProperty.Name]; 
                DiagnosticUtility.DebugAssert(property != null, "WorkerProcess.Register() ConnectionMessageProperty not found!");
 
                IConnection connection = property as IConnection;
                DiagnosticUtility.DebugAssert(connection != null, "WorkerProcess.Register() ConnectionMessageProperty is not IConnection!");

                PipeHandle pipe = connection.GetCoreTransport() as PipeHandle; 
                DiagnosticUtility.DebugAssert(pipe != null, "WorkerProcess.Register() CoreTransport is not PipeHandle!");
 
                if (processId != pipe.GetClientPid()) 
                {
                    status = ListenerExceptionStatus.InvalidArgument; 
                    abortInstance = true;
                    goto FAILED;
                }
            } 

            // validate version 
            Version ourVersion = Assembly.GetExecutingAssembly().GetName().Version; 
            if (version > ourVersion)
            { 
                // VERSIONING
                // in V1 we assume that we can handle earlier versions
                // this might not be true when we ship later releases.
                Debug.Print("WorkerProcess.Register() unsupported version ourVersion: " + ourVersion + " version: " + version); 
                status = ListenerExceptionStatus.VersionUnsupported;
                goto FAILED; 
            } 

            if (queueId == 0 && path == null) 
            {
                status = ListenerExceptionStatus.InvalidArgument;
                abortInstance = true;
                goto FAILED; 
            }
 
            this.processId = processId; 
            this.queueId = 0;
            if (queueId != 0) 
            {
                this.queueId = queueId;
                status = ActivatedMessageQueue.Register(queueId, token, this);
            } 
            else
            { 
                status = MessageQueue.Register(path, this); 
            }
 
            if (status == ListenerExceptionStatus.Success)
            {
                foreach (IChannel channel in OperationContext.Current.InstanceContext.IncomingChannels)
                { 
                    channel.Faulted += new EventHandler(WorkerProcess_Faulted);
                    channel.Closed += new EventHandler(WorkerProcess_Closed); 
                } 

                try 
                {
                    using (EventWaitHandle securityEvent = EventWaitHandle.OpenExisting(ListenerConstants.GlobalPrefix + eventName, EventWaitHandleRights.Modify))
                    {
                        securityEvent.Set(); 
                    }
                } 
                catch (Exception exception) 
                {
                    if (DiagnosticUtility.IsFatal(exception)) 
                    {
                        throw;
                    }
 
                    if (DiagnosticUtility.ShouldTraceError)
                    { 
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error); 
                    }
 
                    status = ListenerExceptionStatus.InvalidArgument;
                    abortInstance = true;
                }
            } 

            if (status != ListenerExceptionStatus.Success) 
            { 
                goto FAILED;
            } 

            if (DiagnosticUtility.ShouldTraceInformation)
            {
                ListenerTraceUtility.TraceEvent(TraceEventType.Information, TraceCode.MessageQueueRegisterSucceeded, new StringTraceRecord("Path", path.ToString()), this, null); 
            }
 
FAILED: 
            if (abortInstance)
            { 
                if (DiagnosticUtility.ShouldTraceError)
                {
                    ListenerTraceUtility.TraceEvent(TraceEventType.Error, TraceCode.MessageQueueRegisterFailed,
                        new StringTraceRecord("Register", SR.GetString(SR.SharingRegistrationFailedAndAbort, status.ToString())), this, null); 
                }
 
                AbortServiceInstance(); 
            }
            else if (status != ListenerExceptionStatus.Success) 
            {
                if (DiagnosticUtility.ShouldTraceError)
                {
                    ListenerTraceUtility.TraceEvent(TraceEventType.Error, TraceCode.MessageQueueRegisterFailed, 
                        new StringTraceRecord("Register", SR.GetString(SR.SharingRegistrationFailed, status.ToString())), this, null);
                } 
 
                InitiateClosingServiceInstance();
            } 

            return status;
        }
 
        bool IConnectionRegister.ValidateUriRoute(Uri uri, System.Net.IPAddress address, int port)
        { 
            if (this.queue == null) 
            {
                AbortServiceInstance(); 
                return false;
            }

            MessageQueue destinationQueue = RoutingTable.Lookup(uri, address, port); 
            return object.ReferenceEquals(destinationQueue, this.queue);
        } 
 
        void IConnectionRegister.Unregister()
        { 
            Debug.Print("WorkerProcess.Unregister() processId: " + processId);
            Close();
        }
 
        static bool ShouldRecoverFromProxyCall(Exception exception)
        { 
            return ( 
                (exception is CommunicationException) ||
                (exception is ObjectDisposedException) || 
                (exception is TimeoutException)
                );
        }
 
        void AbortServiceInstance()
        { 
            OperationContext.Current.InstanceContext.Abort(); 
        }
 
        void InitiateClosingServiceInstance()
        {
            InstanceContext serviceInstance = OperationContext.Current.InstanceContext;
            serviceInstance.BeginClose(ListenerConstants.RegistrationCloseTimeout, 
                DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(CloseCallback)), serviceInstance);
        } 
 
        static void CloseCallback(IAsyncResult asyncResult)
        { 
            InstanceContext serviceInstance = asyncResult.AsyncState as InstanceContext;
            try
            {
                serviceInstance.EndClose(asyncResult); 
            }
            catch (CommunicationException e) 
            { 
                if (DiagnosticUtility.ShouldTraceInformation)
                { 
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                }
            }
            catch (TimeoutException e) 
            {
                if (DiagnosticUtility.ShouldTraceInformation) 
                { 
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                } 
            }
        }

        class DispatchSessionAsyncResult : AsyncResult 
        {
            ListenerSessionConnection session; 
            bool duplicateSucceeded; 
            static AsyncCallback dispatchSessionCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(DispatchSessionCompletedCallback));
 
            public DispatchSessionAsyncResult(ListenerSessionConnection session, AsyncCallback callback, object state)
                : base(callback, state)
            {
                this.session = session; 

                DuplicateContext duplicateContext = session.WorkerProcess.DuplicateConnection(session); 
                if (duplicateContext == null) 
                {
                    // Failed in duplicate connection data. 
                    this.Complete(true);
                }

                IAsyncResult result = this.session.WorkerProcess.ConnectionDuplicator.BeginDuplicate(duplicateContext, 
                    dispatchSessionCallback, this);
 
                if (result.CompletedSynchronously) 
                {
                    CompleteDuplicateSession(result); 
                    this.Complete(true);
                }
            }
 
            static void DispatchSessionCompletedCallback(IAsyncResult result)
            { 
                if (result.CompletedSynchronously) 
                    return;
 
                DispatchSessionAsyncResult thisPtr = (DispatchSessionAsyncResult)result.AsyncState;

                Exception completeException = null;
 
                try
                { 
                    thisPtr.CompleteDuplicateSession(result); 
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception exception)
                {
                    if (DiagnosticUtility.IsFatal(exception))
                    { 
                        throw;
                    } 
 
                    completeException = exception;
                } 

                thisPtr.Complete(false, completeException);
            }
 
            void CompleteDuplicateSession(IAsyncResult result)
            { 
                this.session.WorkerProcess.ConnectionDuplicator.EndDuplicate(result); 

                // Successfully duplicated the session. 
                duplicateSucceeded = true;
            }

            public bool DuplicateSucceeded 
            {
                get 
                { 
                    return duplicateSucceeded;
                } 
            }

            public static DispatchSessionAsyncResult End(IAsyncResult result)
            { 
                return AsyncResult.End(result);
            } 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK