Example #1
0
        private void ExecutionThreadEntry(RemoteConnection connection)
        {
            if (returnImmediately)
            {
                // only happens in calls from the browser to the renderer
                CfxDebug.Assert(connection == RemoteClient.connection);
                ExecuteInTargetProcess(connection);
                return;
            }

            if (RemoteClient.connection == null)
            {
                if (!CfxRemoteCallbackManager.IncrementCallbackCount(connection.remoteProcessId))
                {
                    // The application has suspended remote callbacks.
                    // Write the response without ececuting event handlers, returning default values.
                    connection.EnqueueWrite(WriteResponse);
                    return;
                }
            }

            var threadContext = new CfxRemoteCallContext(connection, remoteThreadId);

            threadContext.Enter();
            var threadStackCount = CfxRemoteCallContext.ContextStackCount;

            try {
                ExecuteInTargetProcess(connection);
            } finally {
                if (RemoteClient.connection == null)
                {
                    CfxRemoteCallbackManager.DecrementCallbackCount(connection.remoteProcessId);
                }
                if (threadStackCount != CfxRemoteCallContext.ContextStackCount || CfxRemoteCallContext.CurrentContext != threadContext)
                {
                    CfxRemoteCallContext.resetStack(threadStackCount - 1);
                    throw new CfxException("Unbalanced remote call context stack. Make sure to balance calls to CfxRemoteCallContext.Enter() and CfxRemoteCallContext.Exit() in all render process callback events.");
                }
                threadContext.Exit();
            }

            connection.EnqueueWrite(WriteResponse);
        }
Example #2
0
        internal void RequestExecution(RemoteConnection connection)
        {
            if (returnImmediately)
            {
                connection.Write(WriteRequest);
                return;
            }

            if (CfxRemoteCallContext.IsInContext && CfxRemoteCallContext.CurrentContext.connection != connection)
            {
                // The thread is in a remote call context, but the requestor wants to call
                // on another connection. This can happen if a CfrObject method from one connection
                // is used within the scope of a callback from another connection.
                // In this case, the call has to be made in a temporary context with remote thread id zero.
                var ctx = new CfxRemoteCallContext(connection, 0);
                ctx.Enter();
                try {
                    RequestExecution(connection);
                } finally {
                    ctx.Exit();
                }
                return;
            }

            localThreadId  = System.Threading.Thread.CurrentThread.ManagedThreadId;
            remoteThreadId = CfxRemoteCallContext.currentThreadId;

            connection.SendRequestAndWait(this);

            if (connection.connectionLostException != null)
            {
                if (RemoteClient.connection != null)
                {
                    // this is the render process calling back into the browser process
                    // reaching this point usually means the browser process crashed or was killed
                    // don't throw, just return so the process can exit gracefully
                    return;
                }
                // throw exception in the browser process
                throw new CfxRemotingException("Remote connection lost.", connection.connectionLostException);
            }
        }
Example #3
0
        /// <summary>
        /// Prepares and executes the remote procedure in the remote process
        /// </summary>
        internal void Execute(RemoteConnection connection)
        {
            if (returnImmediately)
            {
                RemoteProcedure();
                return;
            }

            if (RemoteClient.connection == null)
            {
                if (!CfxRemoteCallbackManager.IncrementCallbackCount(connection.remoteProcessId))
                {
                    // The application has suspended remote callbacks.
                    // Return without ececuting event handlers, connection will return default values.
                    return;
                }
            }

            var threadContext = new CfxRemoteCallContext(connection, remoteThreadId);

            threadContext.Enter();
            var threadStackCount = CfxRemoteCallContext.ContextStackCount;

            try {
                RemoteProcedure();
            } finally {
                if (RemoteClient.connection == null)
                {
                    CfxRemoteCallbackManager.DecrementCallbackCount(connection.remoteProcessId);
                }
                if (threadStackCount != CfxRemoteCallContext.ContextStackCount || CfxRemoteCallContext.CurrentContext != threadContext)
                {
                    CfxRemoteCallContext.resetStack(threadStackCount - 1);
                    throw new CfxException("Unbalanced remote call context stack. Make sure to balance calls to CfxRemoteCallContext.Enter() and CfxRemoteCallContext.Exit() in all render process callback events.");
                }
                threadContext.Exit();
            }
        }
 public void Dispose()
 {
     _CfxRemoteCallContext.Exit();
 }
Example #5
0
        internal void RequestExecution(RemoteConnection connection)
        {
            if (CfxRemoteCallContext.IsInContext && CfxRemoteCallContext.CurrentContext.connection != connection)
            {
                // The thread is in a remote call context, but the requestor wants to call
                // on another connection. This can happen if a CfrObject method from one connection
                // is used within the scope of a callback from another connection.
                // In this case, the call has to be made in a temporary context with remote thread id zero.
                var ctx = new CfxRemoteCallContext(connection, 0);
                ctx.Enter();
                try {
                    RequestExecution(connection);
                } finally {
                    ctx.Exit();
                }
                return;
            }

            if (returnImmediately)
            {
                if (connection.ShuttingDown)
                {
                    return;
                }
                else if (connection.connectionLostException != null)
                {
                    throw new CfxRemotingException("Remote connection lost.", connection.connectionLostException);
                }
                connection.Write(WriteRequest);
                return;
            }


            lock (waitLock) {
                // The lock must begin here. Otherwise,
                // there is a race between Wait and PulseAll
                // causing this thread to wait forever
                // under some circumstances.

                localThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
                connection.callStack.Push(this);

                remoteThreadId = CfxRemoteCallContext.currentThreadId;

                connection.Write(WriteRequest);

                for (; ;)
                {
                    if (responseReceived)
                    {
                        Debug.Assert(reentryCall == null);
                        return;
                    }

                    if (this.reentryCall != null)
                    {
                        reentryCall.ExecutionThreadEntry(connection);
                        reentryCall = null;
                    }

                    if (!connection.ShuttingDown && connection.connectionLostException == null)
                    {
                        System.Threading.Monitor.Wait(waitLock);
                    }

                    if (connection.ShuttingDown)
                    {
                        return;
                    }
                    else if (connection.connectionLostException != null)
                    {
                        if (RemoteClient.connection != null)
                        {
                            // this is the render process calling back into the browser process
                            // reaching this point usually means the browser process crashed or was killed
                            // don't throw, just return so the process can exit gracefully
                            return;
                        }
                        throw new CfxRemotingException("Remote connection lost.", connection.connectionLostException);
                    }
                }
            }
        }
Example #6
0
        private void ExecutionThreadEntry(RemoteConnection connection)
        {
            if(returnImmediately) {
                // only happens in calls from the browser to the renderer
                CfxDebug.Assert(connection == RemoteClient.connection);
                ExecuteInTargetProcess(connection);
                return;
            }

            if(RemoteClient.connection == null) {
                if(!CfxRemoteCallbackManager.IncrementCallbackCount(connection.remoteProcessId)) {
                    // The application has suspended remote callbacks.
                    // Write the response without ececuting event handlers, returning default values.
                    connection.EnqueueWrite(WriteResponse);
                    return;
                }
            }

            var threadContext = new CfxRemoteCallContext(connection, remoteThreadId);
            threadContext.Enter();
            var threadStackCount = CfxRemoteCallContext.ContextStackCount;

            try {
                ExecuteInTargetProcess(connection);
            } finally {
                if(RemoteClient.connection == null) {
                    CfxRemoteCallbackManager.DecrementCallbackCount(connection.remoteProcessId);
                }
                if(threadStackCount != CfxRemoteCallContext.ContextStackCount || CfxRemoteCallContext.CurrentContext != threadContext) {
                    CfxRemoteCallContext.resetStack(threadStackCount - 1);
                    throw new CfxException("Unbalanced remote call context stack. Make sure to balance calls to CfxRemoteCallContext.Enter() and CfxRemoteCallContext.Exit() in all render process callback events.");
                }
                threadContext.Exit();
            }

            connection.EnqueueWrite(WriteResponse);
        }
Example #7
0
        internal void RequestExecution(RemoteConnection connection)
        {
            if(CfxRemoteCallContext.IsInContext && CfxRemoteCallContext.CurrentContext.connection != connection) {
                // The thread is in a remote call context, but the requestor wants to call
                // on another connection. This can happen if a CfrObject method from one connection
                // is used within the scope of a callback from another connection.
                // In this case, the call has to be made in a temporary context with remote thread id zero.
                var ctx = new CfxRemoteCallContext(connection, 0);
                ctx.Enter();
                try {
                    RequestExecution(connection);
                } finally {
                    ctx.Exit();
                }
                return;
            }

            if(returnImmediately) {
                if(connection.ShuttingDown)
                    return;
                else if(connection.connectionLostException != null)
                    throw new CfxRemotingException("Remote connection lost.", connection.connectionLostException);
                connection.EnqueueWrite(WriteRequest);
                return;
            }

            lock(waitLock) {

                // The lock must begin here. Otherwise,
                // there is a race between Wait and PulseAll
                // causing this thread to wait forever
                // under some circumstances.

                localThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
                connection.callStack.Push(this);

                remoteThreadId = CfxRemoteCallContext.currentThreadId;

                connection.EnqueueWrite(WriteRequest);

                for(; ; ) {

                    if(responseReceived) {
                        Debug.Assert(reentryCall == null);
                        return;
                    }

                    if(this.reentryCall != null) {
                        reentryCall.ExecutionThreadEntry(connection);
                        reentryCall = null;
                    }

                    if(!connection.ShuttingDown && connection.connectionLostException == null)
                        System.Threading.Monitor.Wait(waitLock);

                    if(connection.ShuttingDown)
                        return;
                    else if(connection.connectionLostException != null) {
                        if(RemoteClient.connection != null) {
                            // this is the render process calling back into the browser process
                            // reaching this point usually means the browser process crashed or was killed
                            // don't throw, just return so the process can exit gracefully
                            return;
                        }
                        throw new CfxRemotingException("Remote connection lost.", connection.connectionLostException);
                    }
                }
            }
        }