コード例 #1
0
        public virtual async Task AttachSingleThreadedSleeper()
        {
            // http://pytools.codeplex.com/discussions/285741 1/12/2012 6:20 PM
            Process p = Process.Start(Version.InterpreterPath, "\"" + TestData.GetPath(@"TestData\DebuggerProject\AttachSingleThreadedSleeper.py") + "\"");

            try {
                Thread.Sleep(1000);

                var attached = new TaskCompletionSource <bool>();

                var proc = PythonProcess.Attach(p.Id);
                try {
                    proc.ProcessLoaded += (sender, args) => {
                        attached.SetResult(true);
                    };
                    await proc.StartListeningAsync();

                    using (var dumpWriter = new MiniDumpWriter(p)) {
                        await attached.Task.WithTimeout(10000, "Failed to attach within 10s");

                        await proc.ResumeAsync(TimeoutToken());

                        Debug.WriteLine("Waiting for exit");
                        dumpWriter.Cancel();
                    }
                } finally {
                    TerminateProcess(proc);
                }
            } finally {
                DisposeProcess(p);
            }
        }
コード例 #2
0
        public virtual async Task AttachWithOutputRedirection()
        {
            var expectedOutput = new[] { "stdout", "stderr" };

            string script = TestData.GetPath(@"TestData\DebuggerProject\AttachOutput.py");
            var    p      = Process.Start(Version.InterpreterPath, "\"" + script + "\"");

            try {
                using (var dumpWriter = new MiniDumpWriter(p)) {
                    Thread.Sleep(1000);
                    var proc = PythonProcess.Attach(p.Id, PythonDebugOptions.RedirectOutput);
                    try {
                        var attached = new TaskCompletionSource <bool>();
                        proc.ProcessLoaded += (sender, args) => {
                            Console.WriteLine("Process loaded");
                            attached.SetResult(true);
                        };
                        await proc.StartListeningAsync();

                        await attached.Task.WithTimeout(20000, "Failed to attach within 20s");

                        await proc.ResumeAsync(TimeoutToken());

                        var          bpHit  = new TaskCompletionSource <bool>();
                        PythonThread thread = null;
                        proc.BreakpointHit += (sender, args) => {
                            thread = args.Thread;
                            bpHit.SetResult(true);
                        };
                        var bp = proc.AddBreakpoint(script, 5);
                        await bp.AddAsync(TimeoutToken());

                        await bpHit.Task.WithTimeout(20000, "Failed to hit breakpoint within 20s");

                        Assert.IsNotNull(thread);

                        var actualOutput = new List <string>();
                        proc.DebuggerOutput += (sender, e) => {
                            Console.WriteLine("Debugger output: '{0}'", e.Output);
                            actualOutput.Add(e.Output);
                        };

                        var frame = thread.Frames[0];
                        Assert.AreEqual("False", (await frame.ExecuteTextAsync("attached", ct: CancellationTokens.After15s)).StringRepr);
                        await frame.ExecuteTextAsync("attached = True", ct : TimeoutToken());

                        await proc.ResumeAsync(TimeoutToken());

                        WaitForExit(proc);
                        AssertUtil.ArrayEquals(expectedOutput, actualOutput);
                    } finally {
                        await DetachProcessAsync(proc);
                    }

                    dumpWriter.Cancel();
                }
            } finally {
                DisposeProcess(p);
            }
        }
コード例 #3
0
        public virtual async Task AttachAndStepWithBlankSysPrefix()
        {
            string script = TestData.GetPath(@"TestData\DebuggerProject\InfiniteRunBlankPrefix.py");
            var    p      = Process.Start(Version.InterpreterPath, "\"" + script + "\"");

            try {
                using (var dumpWriter = new MiniDumpWriter(p)) {
                    Thread.Sleep(1000);
                    var proc = PythonProcess.Attach(p.Id);
                    try {
                        var attached = new TaskCompletionSource <bool>();
                        proc.ProcessLoaded += async(sender, args) => {
                            Console.WriteLine("Process loaded");
                            await proc.ResumeAsync(TimeoutToken());

                            attached.SetResult(true);
                        };
                        await proc.StartListeningAsync();

                        await attached.Task.WithTimeout(20000, "Failed to attach within 20s");

                        var              bpHit    = new TaskCompletionSource <bool>();
                        PythonThread     thread   = null;
                        PythonStackFrame oldFrame = null;
                        proc.BreakpointHit += (sender, args) => {
                            Console.WriteLine("Breakpoint hit");
                            thread   = args.Thread;
                            oldFrame = args.Thread.Frames[0];
                            bpHit.SetResult(true);
                        };
                        var bp = proc.AddBreakpoint(script, 6);
                        await bp.AddAsync(TimeoutToken());

                        await bpHit.Task.WithTimeout(20000, "Failed to hit breakpoint within 20s");

                        var stepComplete          = new TaskCompletionSource <bool>();
                        PythonStackFrame newFrame = null;
                        proc.StepComplete += (sender, args) => {
                            newFrame = args.Thread.Frames[0];
                            stepComplete.SetResult(true);
                        };
                        await thread.StepOverAsync(TimeoutToken());

                        await stepComplete.Task.WithTimeout(20000, "Failed to complete the step within 20s");

                        Assert.AreEqual(oldFrame.FileName, newFrame.FileName);
                        Assert.IsTrue(oldFrame.LineNo + 1 == newFrame.LineNo);
                    } finally {
                        await DetachProcessAsync(proc);
                    }

                    dumpWriter.Cancel();
                }
            } finally {
                DisposeProcess(p);
            }
        }
コード例 #4
0
        public virtual async Task AttachReattach()
        {
            Process p = Process.Start(Version.InterpreterPath, "\"" + TestData.GetPath(@"TestData\DebuggerProject\InfiniteRun.py") + "\"");

            try {
                using (var dumpWriter = new MiniDumpWriter(p)) {
                    Thread.Sleep(1000);

                    for (int i = 0; i < 10; i++)
                    {
                        Console.WriteLine(i);

                        var attached = new TaskCompletionSource <bool>();
                        var detached = new TaskCompletionSource <bool>();

                        var proc = PythonProcess.Attach(p.Id);

                        proc.ProcessLoaded += (sender, args) => {
                            attached.SetResult(true);
                        };
                        proc.ProcessExited += (sender, args) => {
                            detached.SetResult(true);
                        };
                        await proc.StartListeningAsync(20000);

                        await attached.Task.WithTimeout(10000, "Failed to attach within 10s");

                        await proc.DetachAsync(TimeoutToken());

                        await detached.Task.WithTimeout(10000, "Failed to detach within 10s");
                    }

                    dumpWriter.Cancel();
                }
            } finally {
                DisposeProcess(p);
            }
        }
コード例 #5
0
        public async Task AttachPtvsd()
        {
            var expectedOutput = new[] { "stdout", "stderr" };

            string script = TestData.GetPath(@"TestData\DebuggerProject\AttachPtvsd.py");
            var    psi    = new ProcessStartInfo(Version.InterpreterPath, PtvsdInterpreterArguments + " \"" + script + "\"")
            {
                WorkingDirectory       = TestData.GetPath(),
                UseShellExecute        = false,
                RedirectStandardOutput = true,
                RedirectStandardError  = true,
                CreateNoWindow         = true
            };

            var p = Process.Start(psi);

            try {
                using (var dumpWriter = new MiniDumpWriter(p)) {
                    PythonProcess proc = null;
                    for (int i = 0; ; ++i)
                    {
                        Thread.Sleep(1000);
                        try {
                            proc = await PythonRemoteProcess.AttachAsync(
                                new Uri("tcp://secret@localhost?opt=" + PythonDebugOptions.RedirectOutput),
                                false, TimeoutToken());

                            break;
                        } catch (SocketException) {
                            // Failed to connect - the process might have not started yet, so keep trying a few more times.
                            if (i >= 5 || p.HasExited)
                            {
                                throw;
                            }
                        }
                    }

                    try {
                        var attached = new TaskCompletionSource <bool>();
                        proc.ProcessLoaded += async(sender, e) => {
                            Console.WriteLine("Process loaded");

                            var bp = proc.AddBreakpoint(script, 10);
                            await bp.AddAsync(TimeoutToken());

                            await proc.ResumeAsync(TimeoutToken());

                            attached.SetResult(true);
                        };

                        var actualOutput = new List <string>();
                        proc.DebuggerOutput += (sender, e) => {
                            actualOutput.Add(e.Output);
                        };

                        var bpHit = new TaskCompletionSource <bool>();
                        proc.BreakpointHit += async(sender, args) => {
                            Console.WriteLine("Breakpoint hit");
                            bpHit.SetResult(true);
                            await proc.ResumeAsync(TimeoutToken());
                        };

                        await proc.StartListeningAsync();

                        await attached.Task.WithTimeout(20000, "Failed to attach within 20s");

                        await bpHit.Task.WithTimeout(20000, "Failed to hit breakpoint within 20s");

                        p.WaitForExit(DefaultWaitForExitTimeout);
                        AssertUtil.ArrayEquals(expectedOutput, actualOutput);
                    } finally {
                        await DetachProcessAsync(proc);
                    }

                    dumpWriter.Cancel();
                }
            } finally {
                Console.WriteLine(p.StandardOutput.ReadToEnd());
                Console.WriteLine(p.StandardError.ReadToEnd());
                DisposeProcess(p);
            }
        }
コード例 #6
0
        private async Task AttachTestTimeoutAsync(string hostCode)
        {
            var exe = CompileCode(hostCode);

            // start the test process w/ our handle
            var              eventName = Guid.NewGuid().ToString();
            EventWaitHandle  handle    = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
            ProcessStartInfo psi       = new ProcessStartInfo(exe, eventName);

            psi.UseShellExecute       = false;
            psi.RedirectStandardError = psi.RedirectStandardOutput = true;
            psi.CreateNoWindow        = true;
            // Add Python to PATH so that the host can locate the DLL in case it's not in \Windows\System32 (e.g. for EPD)
            psi.EnvironmentVariables["PATH"] = Environment.GetEnvironmentVariable("PATH") + ";" + Path.GetDirectoryName(Version.InterpreterPath);

            Process p       = Process.Start(psi);
            var     outRecv = new OutputReceiver();

            p.OutputDataReceived += outRecv.OutputDataReceived;
            p.ErrorDataReceived  += outRecv.OutputDataReceived;
            p.BeginErrorReadLine();
            p.BeginOutputReadLine();

            try {
                using (var dumpWriter = new MiniDumpWriter(p)) {
                    bool isAttached = false;

                    // Start the attach with the GIL held.

                    var attachStarted = new TaskCompletionSource <bool>();
                    var attachDone    = new TaskCompletionSource <bool>();

                    // We run the Attach and StartListeningAsync on a separate thread,
                    // because StartListeningAsync waits until debuggee has connected
                    // back (which it won't do until handle is set).
                    var attachTask = Task.Run(async() => {
                        var proc = PythonProcess.Attach(p.Id);
                        try {
                            proc.ProcessLoaded += (sender, args) => {
                                attachDone.SetResult(true);
                                isAttached = true;
                            };

                            attachStarted.SetResult(true);
                            await proc.StartListeningAsync(10000);
                        } finally {
                            await DetachProcessAsync(proc);
                        }
                    });

                    await Task.WhenAny(attachTask, attachStarted.Task).Unwrap().WithTimeout(10000, "Failed to start attaching within 10s");

                    Assert.IsFalse(isAttached, "Should not have attached yet"); // we should be blocked

                    handle.Set();                                               // let the code start running

                    await Task.WhenAny(attachTask, attachDone.Task).Unwrap().WithTimeout(10000, "Failed to attach within 10s");

                    dumpWriter.Cancel();
                }
            } finally {
                Debug.WriteLine(String.Format("Process output: {0}", outRecv.Output.ToString()));
                DisposeProcess(p);
            }
        }
コード例 #7
0
        public virtual async Task AttachThreadingStartNewThread()
        {
            // http://pytools.codeplex.com/workitem/638
            // http://pytools.codeplex.com/discussions/285741#post724014
            var psi = new ProcessStartInfo(Version.InterpreterPath, "\"" + TestData.GetPath(@"TestData\DebuggerProject\ThreadingStartNewThread.py") + "\"");

            psi.WorkingDirectory = TestData.GetPath(@"TestData\DebuggerProject");
            psi.EnvironmentVariables["PYTHONPATH"] = @"..\..";
            psi.UseShellExecute        = false;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError  = true;
            Process p = Process.Start(psi);

            try {
                using (var dumpWriter = new MiniDumpWriter(p)) {
                    if (p.WaitForExit(1000))
                    {
                        Assert.Fail("Process exited");
                    }

                    var proc = PythonProcess.Attach(p.Id);
                    try {
                        var attached            = new TaskCompletionSource <bool>();
                        var readyToContinue     = new TaskCompletionSource <bool>();
                        var threadBreakpointHit = new TaskCompletionSource <bool>();

                        proc.ProcessLoaded += async(sender, args) => {
                            attached.TrySetResult(true);
                            var bp = proc.AddBreakpoint("ThreadingStartNewThread.py", 9);
                            await bp.AddAsync(TimeoutToken());

                            bp = proc.AddBreakpoint("ThreadingStartNewThread.py", 5);
                            await bp.AddAsync(TimeoutToken());

                            await proc.ResumeAsync(TimeoutToken());
                        };

                        PythonThread mainThread = null;
                        PythonThread bpThread   = null;
                        bool         wrongLine  = false;
                        proc.BreakpointHit += async(sender, args) => {
                            if (args.Breakpoint.LineNo == 9)
                            {
                                // stop running the infinite loop
                                Debug.WriteLine(String.Format("First BP hit {0}", args.Thread.Id));
                                mainThread = args.Thread;
                                await args.Thread.Frames[0].ExecuteTextAsync(
                                    "x = False",
                                    x => readyToContinue.TrySetResult(true),
                                    TimeoutToken());
                            }
                            else if (args.Breakpoint.LineNo == 5)
                            {
                                // we hit the breakpoint on the new thread
                                Debug.WriteLine(String.Format("Second BP hit {0}", args.Thread.Id));
                                bpThread = args.Thread;
                                threadBreakpointHit.TrySetResult(true);
                                await proc.ResumeAsync(TimeoutToken());
                            }
                            else
                            {
                                Debug.WriteLine(String.Format("Hit breakpoint on wrong line number: {0}", args.Breakpoint.LineNo));
                                wrongLine = true;
                                attached.TrySetResult(true);
                                threadBreakpointHit.TrySetResult(true);
                                await proc.ResumeAsync(TimeoutToken());
                            }
                        };

                        await proc.StartListeningAsync();

                        await attached.Task.WithTimeout(30000, "Failed to attach within 30s");

                        await readyToContinue.Task.WithTimeout(30000, "Failed to hit the main thread breakpoint within 30s");

                        await proc.ResumeAsync(TimeoutToken());

                        await threadBreakpointHit.Task.WithTimeout(30000, "Failed to hit the background thread breakpoint within 30s");

                        Assert.IsFalse(wrongLine, "Breakpoint broke on the wrong line");

                        Assert.AreNotEqual(mainThread, bpThread);
                    } finally {
                        await DetachProcessAsync(proc);
                    }
                }
            } finally {
                DisposeProcess(p);
            }
        }
コード例 #8
0
        public virtual async Task AttachNewThread_PyThreadState_New()
        {
            var hostCode = @"#include <Windows.h>
#include <process.h>
#include <Python.h>

PyObject *g_pFunc;

void Thread(void*)
{
    printf(""Worker thread started %x\r\n"", GetCurrentThreadId());
    while (true)
    {
        PyEval_AcquireLock();
        PyInterpreterState* pMainInterpreterState = PyInterpreterState_Head();
        auto pThisThreadState = PyThreadState_New(pMainInterpreterState);
        PyThreadState_Swap(pThisThreadState);

        PyObject *pValue;

        pValue = PyObject_CallObject(g_pFunc, 0);
        if (pValue != NULL) {
            //printf(""Result of call: %ld\n"", PyInt_AsLong(pValue));
            Py_DECREF(pValue);
        }
        else {
            PyErr_Print();
            return;
        }

        PyThreadState_Swap(NULL);
        PyThreadState_Clear(pThisThreadState);
        PyThreadState_Delete(pThisThreadState);
        PyEval_ReleaseLock();

        Sleep(1000);
    }
}

void main()
{
    PyObject *pName, *pModule;

    Py_SetPythonHome($PYTHON_HOME);
    Py_Initialize();
    PyEval_InitThreads();
    pName = CREATE_STRING(""gilstate_attach"");

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL) {
        g_pFunc = PyObject_GetAttrString(pModule, ""test"");

        if (g_pFunc && PyCallable_Check(g_pFunc))
        {
            DWORD threadID;
            threadID = _beginthread(&Thread, 1024*1024, 0);
            threadID = _beginthread(&Thread, 1024*1024, 0);
            PyEval_ReleaseLock();

            while (true);
        }
        else
        {
            if (PyErr_Occurred())
                PyErr_Print();
        }
        Py_XDECREF(g_pFunc);
        Py_DECREF(pModule);
    }
    else
    {
        PyErr_Print();
        return;
    }
    Py_Finalize();
    return;
}".Replace("CREATE_STRING", CreateString);
            var exe      = CompileCode(hostCode);

            File.WriteAllText(Path.Combine(Path.GetDirectoryName(exe), "gilstate_attach.py"), @"def test():
    for i in range(10):
        print(i)

    return 0");


            // start the test process w/ our handle
            Process p = RunHost(exe);

            try {
                using (var dumpWriter = new MiniDumpWriter(p)) {
                    Thread.Sleep(1500);

                    var attached = new TaskCompletionSource <bool>();
                    var bpHit    = new TaskCompletionSource <bool>();

                    var proc = PythonProcess.Attach(p.Id);
                    try {
                        proc.ProcessLoaded += (sender, args) => {
                            Console.WriteLine("Process loaded");
                            attached.SetResult(true);
                        };
                        await proc.StartListeningAsync();

                        await attached.Task.WithTimeout(20000, "Failed to attach within 20s");

                        proc.BreakpointHit += (sender, args) => {
                            Console.WriteLine("Breakpoint hit");
                            bpHit.SetResult(true);
                        };

                        var bp = proc.AddBreakpoint("gilstate_attach.py", 3);
                        await bp.AddAsync(TimeoutToken());

                        await bpHit.Task.WithTimeout(20000, "Failed to hit breakpoint within 20s");
                    } finally {
                        await DetachProcessAsync(proc);
                    }

                    dumpWriter.Cancel();
                }
            } finally {
                DisposeProcess(p);
            }
        }