PageRenderTime 28ms CodeModel.GetById 19ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_Main/Runtime/Microsoft.Dynamic/Hosting/Shell/Remote/RemoteCommandDispatcher.cs

#
C# | 96 lines | 49 code | 14 blank | 33 comment | 6 complexity | 4e029e2b02becdb5e7be6186c1f59d54 MD5 | raw file
 1/* ****************************************************************************
 2 *
 3 * Copyright (c) Microsoft Corporation. 
 4 *
 5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
 6 * copy of the license can be found in the License.html file at the root of this distribution. If 
 7 * you cannot locate the  Apache License, Version 2.0, please send an email to 
 8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 9 * by the terms of the Apache License, Version 2.0.
10 *
11 * You must not remove this notice, or any other, from this software.
12 *
13 *
14 * ***************************************************************************/
15
16#if !SILVERLIGHT // Remoting
17
18using System;
19using System.Diagnostics;
20using System.Threading;
21using System.Security.Permissions;
22
23namespace Microsoft.Scripting.Hosting.Shell.Remote {
24    /// <summary>
25    /// This allows the RemoteConsoleHost to abort a long-running operation. The RemoteConsoleHost itself
26    /// does not know which ThreadPool thread might be processing the remote call, and so it needs
27    /// cooperation from the remote runtime server.
28    /// </summary>
29    public class RemoteCommandDispatcher : MarshalByRefObject, ICommandDispatcher {
30        /// <summary>
31        /// Since OnOutputDataReceived is sent async, it can arrive late. The remote console
32        /// cannot know if all output from the current command has been received. So
33        /// RemoteCommandDispatcher writes out a marker to indicate the end of the output
34        /// </summary>
35        internal const string OutputCompleteMarker = "{7FF032BB-DB03-4255-89DE-641CA195E5FA}";
36
37        private ScriptScope _scriptScope;
38        private Thread _executingThread;
39
40        public RemoteCommandDispatcher(ScriptScope scope) {
41            _scriptScope = scope;
42        }
43
44        public ScriptScope ScriptScope { get { return _scriptScope; } }
45
46        public object Execute(CompiledCode compiledCode, ScriptScope scope) {
47            Debug.Assert(_executingThread == null);
48            _executingThread = Thread.CurrentThread;
49
50            try {
51                object result = compiledCode.Execute(scope);
52
53                Console.WriteLine(RemoteCommandDispatcher.OutputCompleteMarker);
54
55                return result;
56            } catch (ThreadAbortException tae) {
57                KeyboardInterruptException pki = tae.ExceptionState as KeyboardInterruptException;
58                if (pki != null) {
59                    // Most exceptions get propagated back to the client. However, ThreadAbortException is handled
60                    // differently by the remoting infrastructure, and gets wrapped in a RemotingException
61                    // ("An error occurred while processing the request on the server"). So we filter it out
62                    // and raise the KeyboardInterruptException
63                    Thread.ResetAbort();
64                    throw pki;
65                } else {
66                    throw;
67                }
68            } finally {
69                _executingThread = null;
70            }
71        }
72
73        /// <summary>
74        /// Aborts the current active call to Execute by doing Thread.Abort
75        /// </summary>
76        /// <returns>true if a Thread.Abort was actually called. false if there is no active call to Execute</returns>
77        public bool AbortCommand() {
78            Thread executingThread = _executingThread;
79            if (executingThread == null) {
80                return false;
81            }
82
83            executingThread.Abort(new KeyboardInterruptException(""));
84            return true;
85        }
86
87#if !SILVERLIGHT
88        // TODO: Figure out what is the right lifetime
89        public override object InitializeLifetimeService() {
90            return null;
91        }
92#endif
93    }
94}
95
96#endif