1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // This file declares the trace::logger::Logger class which implements
16 : // a simple logging service over RPC.
17 :
18 : #ifndef SYZYGY_TRACE_LOGGER_LOGGER_H_
19 : #define SYZYGY_TRACE_LOGGER_LOGGER_H_
20 :
21 : #include "base/callback.h"
22 : #include "base/message_loop.h"
23 : #include "base/string_piece.h"
24 : #include "base/threading/platform_thread.h"
25 : #include "syzygy/trace/rpc/logger_rpc.h"
26 :
27 : namespace trace {
28 : namespace logger {
29 :
30 : // Implements the Logger interface (see "logger_rpc.idl").
31 : //
32 : // Note: The Logger expects to be the only RPC service running in the process.
33 : //
34 : // TODO(rogerm): Add a Write function more amenable to out-of-process ASAN
35 : // error reporting (i.e., accepts module info and stack traces in some
36 : // format).
37 : class Logger {
38 : public:
39 : typedef base::Callback<bool(Logger*)> LoggerCallback;
40 :
41 : enum State {
42 : kStopped,
43 : kInitialized,
44 : kRunning,
45 : kStopping,
46 : };
47 :
48 : Logger();
49 : ~Logger();
50 :
51 : // Set the id for this instance.
52 E : void set_instance_id(const base::StringPiece16& id) {
53 E : DCHECK_EQ(kStopped, state_);
54 E : instance_id_.assign(id.begin(), id.end());
55 E : }
56 :
57 : // Set the destination file for this logger.
58 E : void set_destination(FILE* destination) {
59 E : DCHECK(destination != NULL);
60 E : destination_ = destination;
61 E : }
62 :
63 : // Set a callback to be invoked when the logger has started.
64 E : void set_logger_started_callback(LoggerCallback callback) {
65 E : logger_started_callback_ = callback;
66 E : }
67 :
68 : // Set a callback to be invoked when the logger has stopped.
69 E : void set_logger_stopped_callback(LoggerCallback callback) {
70 E : logger_stopped_callback_ = callback;
71 E : }
72 :
73 : // Begin accepting and handling RPC invocations. This method may only be
74 : // called by the thread which created the logger.
75 : //
76 : // This call is non-blocking. The request handlers will be run on a thread
77 : // pool owned by the RPC runtime.
78 : bool Start();
79 :
80 : // Request that the logger stop. This method be called by any thread once
81 : // the logger has started.
82 : //
83 : // This call is non-blocking. The request handlers run on a thread pool
84 : // owned by the RPC runtime.
85 : bool Stop();
86 :
87 : // Run the logger until is has completely shutdown. This method may only
88 : // be called by the thread which created, and subsequently started, the
89 : // logger.
90 : //
91 : // Following the receipt of an AsyncStop() request, it is the responsibility
92 : // of the thread which owns the logger to ensure that RunToCompletion() is
93 : // called as it will take care of flushing any in-flight log requests to disk
94 : // before terminating.
95 : //
96 : // This is a blocking call, it will return after all outstanding requests
97 : // have been handled and all log messages have been flushed.
98 : bool RunToCompletion();
99 :
100 : // Append a trace dump for @p process, given @p trace_data containing
101 : // @p trace_length elements. The output will be appended to @p message.
102 : //
103 : // Note that the DWORD elements of @p trace_data are really void* values
104 : // pointing to the frame pointers of a call stack in @p process.
105 : //
106 : // Calls to this method are serialized under symbol_lock_.
107 : bool AppendTrace(HANDLE process,
108 : const DWORD* trace_data,
109 : size_t trace_length,
110 : std::string* message);
111 :
112 : // Captures a stack trace in a @p process given a program @p context.
113 : // @param process An open handle to the running process.
114 : // @param context The program context from which to trace.
115 : // @param trace_data The vector into which the trace will be populated.
116 : // @returns true on success, false otherwise.
117 : bool CaptureRemoteTrace(HANDLE process,
118 : CONTEXT* context,
119 : std::vector<DWORD>* trace_data);
120 :
121 : // Write @p message to the log destination. Note that calls to this method
122 : // are serialized using write_lock_.
123 : bool Write(const base::StringPiece& message);
124 :
125 : protected:
126 : // @name RPC Server Management Functions.
127 : // These functions, unless otherwise noted, are single threaded and must
128 : // all be called from the thread that created this instance.
129 : // @{
130 : bool InitRpc();
131 : bool StartRPC();
132 : bool StopRpc(); // This non-blocking function may be called from any thread.
133 : bool FinishRpc(); // This function is blocking.
134 : // @}
135 :
136 : // The ID of the thread that created this logger.
137 : base::PlatformThreadId owning_thread_id_;
138 :
139 : // A unique id to identify this logger instance.
140 : std::wstring instance_id_;
141 :
142 : // The current state of the logger.
143 : State state_;
144 :
145 : // The file to which received log messages should be written. This must
146 : // remain valid for at least as long as the logger is valid. Writes to
147 : // the destination are serialized with lock_;
148 : FILE* destination_;
149 :
150 : // The lock used to serializes writes to destination_;
151 : base::Lock write_lock_;
152 :
153 : // The lock used to serialize access to the debug help library used to
154 : // symbolize traces.
155 : base::Lock symbol_lock_;
156 :
157 : // A callback to be invoked when the logger has successfully started.
158 : LoggerCallback logger_started_callback_;
159 :
160 : // A callback to be invoked when the logger has successfully stopped.
161 : LoggerCallback logger_stopped_callback_;
162 :
163 : private:
164 : DISALLOW_COPY_AND_ASSIGN(Logger);
165 : };
166 :
167 : } // namespace logger
168 : } // namespace trace
169 :
170 : #endif // SYZYGY_TRACE_LOGGER_LOGGER_H_
|