summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Diagnostics/Debugger.cs
blob: cda3c4e729ca5fc5e3601e322644db16020359e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

// The Debugger class is a part of the System.Diagnostics package
// and is used for communicating with a debugger.

using System.Runtime.CompilerServices;

namespace System.Diagnostics
{
    public static class Debugger
    {
        // Break causes a breakpoint to be signalled to an attached debugger.  If no debugger
        // is attached, the user is asked if he wants to attach a debugger. If yes, then the
        // debugger is launched.
        [MethodImpl(MethodImplOptions.NoInlining)]
        public static void Break() => BreakInternal();

        // The VM depends on this private method.
        private static void BreakCanThrow() => BreakInternal();

        [MethodImpl(MethodImplOptions.InternalCall)]
        private static extern void BreakInternal();

        // Launch launches & attaches a debugger to the process. If a debugger is already attached,
        // nothing happens.
        //
        public static bool Launch() => IsAttached ? true : LaunchInternal();

        // This class implements code:ICustomDebuggerNotification and provides a type to be used to notify
        // the debugger that execution is about to enter a path that involves a cross-thread dependency.
        // See code:NotifyOfCrossThreadDependency for more details.
        private class CrossThreadDependencyNotification : ICustomDebuggerNotification { }

        // Do not inline the slow path
        [MethodImpl(MethodImplOptions.NoInlining)]
        private static void NotifyOfCrossThreadDependencySlow() =>
            CustomNotification(new CrossThreadDependencyNotification());

        // Sends a notification to the debugger to indicate that execution is about to enter a path
        // involving a cross thread dependency. A debugger that has opted into this type of notification
        // can take appropriate action on receipt. For example, performing a funceval normally requires
        // freezing all threads but the one performing the funceval. If the funceval requires execution on
        // more than one thread, as might occur in remoting scenarios, the funceval will block. This
        // notification will apprise the debugger that it will need  to slip a thread or abort the funceval
        // in such a situation. The notification is subject to collection after this function returns.
        //
        public static void NotifyOfCrossThreadDependency()
        {
            if (IsAttached)
            {
                NotifyOfCrossThreadDependencySlow();
            }
        }

        [MethodImpl(MethodImplOptions.InternalCall)]
        private static extern bool LaunchInternal();

        // Returns whether or not a debugger is attached to the process.
        //
        public static extern bool IsAttached
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            get;
        }

        // Constants representing the importance level of messages to be logged.
        //
        // An attached debugger can enable or disable which messages will
        // actually be reported to the user through the COM+ debugger
        // services API.  This info is communicated to the runtime so only
        // desired events are actually reported to the debugger.
        //
        // Constant representing the default category
        public static readonly string DefaultCategory = null;

        // Posts a message for the attached debugger.  If there is no
        // debugger attached, has no effect.  The debugger may or may not
        // report the message depending on its settings.
        [MethodImpl(MethodImplOptions.InternalCall)]
        public static extern void Log(int level, string category, string message);

        // Checks to see if an attached debugger has logging enabled
        //
        [MethodImpl(MethodImplOptions.InternalCall)]
        public static extern bool IsLogging();

        // Posts a custom notification for the attached debugger.  If there is no
        // debugger attached, has no effect.  The debugger may or may not
        // report the notification depending on its settings.
        [MethodImpl(MethodImplOptions.InternalCall)]
        private static extern void CustomNotification(ICustomDebuggerNotification data);
    }
}