HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
stackTrace.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_ARCH_STACK_TRACE_H
8 #define PXR_BASE_ARCH_STACK_TRACE_H
9 
10 /// \file arch/stackTrace.h
11 /// \ingroup group_arch_Diagnostics
12 /// Architecture-specific call-stack tracing routines.
13 
14 #include "pxr/pxr.h"
15 #include "pxr/base/arch/api.h"
16 #include "pxr/base/arch/defines.h"
17 
18 #include <inttypes.h>
19 #include <stdio.h>
20 #include <functional>
21 #include <vector>
22 #include <string>
23 #include <iosfwd>
24 #include <ctime>
25 
27 
28 /// \addtogroup group_arch_Diagnostics
29 ///@{
30 
31 /// Dumps call-stack info to a file, prints a message to the terminal, and
32 /// invokes crash handling script.
33 ///
34 /// The reason for the trace should be supplied in \p reason. An additional
35 /// message may be provided in \p message. If \p reason is \c NULL then this
36 /// function only writes \p message to the banner (if any).
37 ///
38 /// This routine can be slow and is intended to be called for a fatal error,
39 /// such as a caught coredump signal. While it can theoretically be called at
40 /// any time, \c ArchLogCurrentProcessState() should be used for nonfatal cases.
41 ///
42 /// This function is implemented by calling an external program. This is
43 /// suitable for times where the current process may be corrupted. In other
44 /// cases, using \c ArchPrintStackTrace() or other related functions would be
45 /// much faster.
46 ///
47 /// Note the use of \c char* as opposed to \c string: this is intentional,
48 /// because we are trying to use only async-safe function from here on and
49 /// malloc() is not async-safe.
51 void ArchLogFatalProcessState(const char* reason,
52  const char* message = nullptr,
53  const char* extraLogMsg = nullptr);
54 
55 /// Dumps call-stack info to a file, and prints an informative message.
56 ///
57 /// The reason for the trace should be supplied in \p reason. An additional
58 /// message may be provided in \p message. If \p reason is \c NULL then this
59 /// function only writes \p message to the banner (if any).
60 ///
61 /// This function is nearly identical to ArchLogFatalProcessState, including
62 /// calling an external program. However, it is intended for cases that may
63 /// simulate or require the output info from a full fatal crash, but are
64 /// not truly fatal errors. For cases where that is not necessary,
65 /// using \c ArchPrintStackTrace() or other related functions would be
66 /// much faster.
67 ///
68 /// Note the use of \c char* as opposed to \c string: this is intentional,
69 /// because we are trying to use only async-safe function from here on and
70 /// malloc() is not async-safe.
72 void ArchLogCurrentProcessState(const char* reason,
73  const char* message = nullptr,
74  const char* extraLogMsg = nullptr);
75 
76 /// Sets command line that gets call-stack info and triggers crash handling
77 /// script.
78 ///
79 /// This function sets the command line to execute to gather and log
80 /// call-stack info. \p argv must be NULL terminated. If \p command and/or \p
81 /// argv (or \p fatalArgv in the case of a fatal crash) are NULL, then
82 /// the command will not be executed. Otherwise argv[0] and fatalArgv[0] must be
83 /// the full path to the program to execute, typically \p command or "$cmd" as
84 /// described below.
85 ///
86 /// \p command, \p argv, and \p fatalArgv are not copied and must remain valid
87 /// until the next call to \c ArchSetProcessStateLogCommand.
88 ///
89 /// Simple substitution is supported on argv elements:
90 /// \li $cmd: Substitutes the command pathname, or $ARCH_POSTMORTEM if set
91 /// \li $pid: Substitutes the process id
92 /// \li $log: Substitutes the log pathname
93 /// \li $time: Substitutes the user time (if available, else wall time)
94 /// \li $reason: Substitutes the reason string for the crash
95 ///
96 /// \sa ArchLogFatalProcessState
98 void ArchSetProcessStateLogCommand(const char* command,
99  const char *const argv[],
100  const char* const fatalArgv[]);
101 
102 /// Returns true if the fatal signal handler ArchLogFatalProcessState
103 /// has been invoked.
104 ARCH_API
105 bool ArchIsAppCrashing();
106 
107 /// Log session info.
108 ///
109 /// Optionally indicate that this is due to a crash by providing
110 /// the path to a file containing a stack trace in \p crashStackTrace.
111 ///
112 ARCH_API
113 void ArchLogSessionInfo(const char *crashStackTrace=NULL);
114 
115 /// Sets the command line to log sessions.
116 ///
117 /// This function sets the command line to execute to log session info. \p
118 /// argv is used if no crash stack trace is provided, otherwise \p crashArgv
119 /// is used. Both must be NULL terminated. If \p command or \p argv is NULL
120 /// then non-crashes are not logged; if \p command or \p crashArgv is NULL
121 /// then crashes are not logged. If not NULL then argv[0] and crashArgv[0]
122 /// must be full path to the program to execute, typically \p command or
123 /// "$cmd" as described below.
124 ///
125 /// \p command, \p argv, and \p crashArgv are not copied and must remain valid
126 /// until the next call to \c ArchSetLogSession.
127 ///
128 /// Simple substitution is supported on argv elements:
129 /// \li $cmd: Substitutes the command pathname, or $ARCH_LOGSESSION if set
130 /// \li $prog Substitutes the program name
131 /// \li $pid: Substitutes the process id
132 /// \li $time: Substitutes the user time (if available, else wall time)
133 /// \li $stack: Substitutes the crash stack string (only in crashArgv)
134 ///
135 /// \sa ArchLogSessionInfo
136 ARCH_API
137 void ArchSetLogSession(const char* command,
138  const char* const argv[],
139  const char* const crashArgv[]);
140 
141 /// Register the callback to invoke logging at end of a successful session.
142 ///
143 /// This function registers ArchLogSessionInfo() and records the current
144 /// timestamp, to send up-time to the DB upon exiting.
145 ARCH_API
147 
148 /// Print a stack trace to the given FILE pointer.
149 ARCH_API
150 void ArchPrintStackTrace(FILE *fout,
151  const std::string& programName,
152  const std::string& reason);
153 
154 /// Print a stack trace to the given FILE pointer.
155 /// This function uses ArchGetProgramInfoForErrors as the \c programName.
156 /// \overload
157 ARCH_API
158 void ArchPrintStackTrace(FILE *fout, const std::string& reason);
159 
160 /// Print a stack trace to the given ostream.
161 /// \overload
162 ARCH_API
163 void ArchPrintStackTrace(std::ostream& out,
164  const std::string& programName,
165  const std::string& reason);
166 
167 /// Print a stack trace to the given ostream.
168 /// This function uses ArchGetProgramInfoForErrors as the \c programName.
169 /// \overload
170 ARCH_API
171 void ArchPrintStackTrace(std::ostream& out, const std::string& reason);
172 
173 /// A callback to get a symbolic representation of an address.
174 typedef std::function<std::string(uintptr_t address)> ArchStackTraceCallback;
175 
176 /// Sets a callback to get a symbolic representation of an address.
177 ///
178 /// The callback returns a string for an address in a stack trace, typically
179 /// including the name of the function containing the address. \p cb may be \c
180 /// NULL to use a default implementation.
181 ARCH_API
183 
184 /// Returns the callback to get a symbolic representation of an address.
185 /// \sa ArchSetStackTraceCallback
186 ARCH_API
188 
189 /// Returns the set value for the application's launch time.
190 /// The timestamp for this value is set when the arch library is initialized.
191 ARCH_API
192 time_t ArchGetAppLaunchTime();
193 
194 /// Enables or disables the automatic logging of crash information.
195 ///
196 /// This function controls whether the stack trace and build information is
197 /// automatically caught and stored to an internal database when a fatal crash
198 /// occurs.
199 ARCH_API
200 void ArchSetFatalStackLogging(bool flag);
201 
202 /// Returns whether automatic logging of fatal crashes is enabled
203 /// This is set to false by default.
204 /// \see ArchSetFatalStackLogging
205 ARCH_API
207 
208 /// Sets the program name to be used in diagnostic output
209 ///
210 /// The default value is initialized to ArchGetExecutablePath().
211 ARCH_API
212 void ArchSetProgramNameForErrors(const char * progName);
213 
214 /// Returns the currently set program name for reporting errors.
215 /// Defaults to ArchGetExecutablePath().
216 ARCH_API
217 const char * ArchGetProgramNameForErrors();
218 
219 /// Sets additional program info to be reported to the terminal in case of a
220 /// fatal error.
221 ARCH_API
222 void ArchSetProgramInfoForErrors( const std::string& key, const std::string& value );
223 
224 /// Returns currently set program info.
225 /// \see ArchSetExtraLogInfoForErrors
226 ARCH_API
227 std::string ArchGetProgramInfoForErrors(const std::string& key);
228 
229 /// Stores (or removes if \p lines is nullptr) a pointer to additional log data
230 /// that will be output in the stack trace log in case of a fatal error. Note
231 /// that the pointer \p lines is copied, not the pointed-to data. In addition,
232 /// Arch might read the data pointed to by \p lines concurrently at any time.
233 /// Thus it is the caller's responsibility to ensure that \p lines is both valid
234 /// and not mutated until replacing or removing it by invoking this function
235 /// again with the same \p key and different \p lines.
236 ARCH_API
237 void ArchSetExtraLogInfoForErrors(const std::string &key,
238  std::vector<std::string> const *lines);
239 
240 /// Logs a stack trace to a file in /var/tmp.
241 ///
242 /// This function is similar to \c ArchLogPostMortem(), but will not fork an
243 /// external process and only reports a stack trace. A file in /var/tmp is
244 /// created with the name \c st_APPNAME.XXXXXX, where \c mktemp is used to
245 /// make a unique extension for the file. If \c sessionLog is specified, then
246 /// it will be appended to this file. A message is printed to \c stderr
247 /// reporting that a stack trace has been taken and what file it has been
248 /// written to. And if \c fatal is true, then the stack trace will be added
249 /// to the stack_trace database table.
250 ARCH_API
251 void ArchLogStackTrace(const std::string& progName,
252  const std::string& reason,
253  bool fatal = false,
254  const std::string& sessionLog = "");
255 
256 /// Logs a stack trace to a file in /var/tmp.
257 ///
258 /// This function is similar to \c ArchLogPostMortem(), but will not fork an
259 /// external process and only reports a stack trace. A file in /var/tmp is
260 /// created with the name \c st_APPNAME.XXXXXX, where \c mktemp is used to
261 /// make a unique extension for the file. If \c sessionLog is specified,
262 /// then it will be appended to this file. A message is printed to \c stderr
263 /// reporting that a stack trace has been taken and what file it has been
264 /// written to. And if \c fatal is true, then the stack trace will be added
265 /// to the stack_trace database table.
266 ARCH_API
267 void ArchLogStackTrace(const std::string& reason,
268  bool fatal = false,
269  const std::string& sessionLog = "");
270 
271 /// Return stack trace.
272 ///
273 /// This function will return a vector of strings containing the current
274 /// stack. The vector will be of maximum size \p maxDepth.
275 ARCH_API
276 std::vector<std::string> ArchGetStackTrace(size_t maxDepth);
277 
278 
279 /// Save frames of current stack
280 ///
281 /// This function saves at maximum \c maxDepth frames of the current stack
282 /// into the vector \c frames.
283 ARCH_API
284 void ArchGetStackFrames(size_t maxDepth, std::vector<uintptr_t> *frames);
285 
286 /// Store at most \p maxDepth frames of the current stack into \p frames.
287 /// Return the number of stack frames written to \p frames.
288 ARCH_API
289 size_t ArchGetStackFrames(size_t maxDepth, uintptr_t *frames);
290 
291 /// Save frames of current stack.
292 ///
293 /// This function saves at maximum \p maxDepth frames of the current stack
294 /// into the vector \p frames, skipping the first \p numFramesToSkipAtTop
295 /// frames. The first frame will be at depth \p numFramesToSkipAtTop and the
296 /// last at depth \p numFramesToSkipAtTop + \p maxDepth - 1.
297 ARCH_API
298 void ArchGetStackFrames(size_t maxDepth, size_t numFramesToSkipAtTop,
299  std::vector<uintptr_t> *frames);
300 
301 /// Store at most \p maxDepth frames of the current stack into \p frames,
302 /// skipping the first \p numFramesToSkipAtTop frames. Return the number of
303 /// stack frames written to \p frames.
304 ARCH_API
305 size_t ArchGetStackFrames(size_t maxDepth, size_t numFramesToSkipAtTop,
306  uintptr_t *frames);
307 
308 
309 /// Print stack frames to the given ostream.
310 ARCH_API
311 void ArchPrintStackFrames(std::ostream& out,
312  const std::vector<uintptr_t> &frames,
313  bool skipUnknownFrames = false);
314 
315 /// Callback for handling crashes.
316 /// \see ArchCrashHandlerSystemv
317 typedef void (*ArchCrashHandlerSystemCB)(void* userData);
318 
319 /// Replacement for 'system' safe for a crash handler
320 ///
321 /// This function is a substitute for system() which does not allocate or free
322 /// any data, and times out after \c timeout seconds if the operation in \c
323 /// argv is not complete. Unlike system, it takes the full \c pathname of the
324 /// program to run, and won't search the path. Also unlike system, \c argv[]
325 /// are the separated arguments, starting with the program's name, as for
326 /// execv. \c callback is called every second. \c userData is passed to \c
327 /// callback. \c callback can be used, for example, to print a '.' repeatedly
328 /// to show progress. The alarm used in this function could interfere with
329 /// setitimer or other calls to alarm, and this function uses non-locking fork
330 /// and exec if available so should not generally be used except following a
331 /// catastrophe.
332 ARCH_API
333 int ArchCrashHandlerSystemv(const char* pathname, char *const argv[],
334  int timeout, ArchCrashHandlerSystemCB callback,
335  void* userData);
336 
337 #if defined(ARCH_OS_DARWIN)
338 // macOS has no ETIME. ECANCELED seems to have about the closest meaning to
339 // the actual error here. The operation is timing out, not being explicitly
340 // canceled, but it is canceled.
341 #ifndef ETIME
342 #define ETIME ECANCELED
343 #endif // end ETIME
344 #endif // end ARCH_OS_DARWIN
345 
346 ///@}
347 
349 
350 #endif // PXR_BASE_ARCH_STACK_TRACE_H
std::function< std::string(uintptr_t address)> ArchStackTraceCallback
A callback to get a symbolic representation of an address.
Definition: stackTrace.h:174
GLuint GLsizei const GLchar * message
Definition: glcorearb.h:2543
ARCH_API void ArchSetProcessStateLogCommand(const char *command, const char *const argv[], const char *const fatalArgv[])
ARCH_API void ArchGetStackFrames(size_t maxDepth, std::vector< uintptr_t > *frames)
void
Definition: png.h:1083
ARCH_API int ArchCrashHandlerSystemv(const char *pathname, char *const argv[], int timeout, ArchCrashHandlerSystemCB callback, void *userData)
uint128_t uintptr_t
Definition: format.h:479
GLsizei const GLfloat * value
Definition: glcorearb.h:824
ARCH_API void ArchLogFatalProcessState(const char *reason, const char *message=nullptr, const char *extraLogMsg=nullptr)
ARCH_API bool ArchIsAppCrashing()
ARCH_API void ArchSetProgramNameForErrors(const char *progName)
ARCH_API void ArchLogSessionInfo(const char *crashStackTrace=NULL)
ARCH_API void ArchPrintStackTrace(FILE *fout, const std::string &programName, const std::string &reason)
Print a stack trace to the given FILE pointer.
ARCH_API void ArchLogStackTrace(const std::string &progName, const std::string &reason, bool fatal=false, const std::string &sessionLog="")
ARCH_API void ArchSetLogSession(const char *command, const char *const argv[], const char *const crashArgv[])
GLbitfield GLuint64 timeout
Definition: glcorearb.h:1599
ARCH_API void ArchLogCurrentProcessState(const char *reason, const char *message=nullptr, const char *extraLogMsg=nullptr)
ARCH_API void ArchGetStackTraceCallback(ArchStackTraceCallback *cb)
ARCH_API void ArchSetStackTraceCallback(const ArchStackTraceCallback &cb)
ARCH_API const char * ArchGetProgramNameForErrors()
ARCH_API bool ArchGetFatalStackLogging()
ARCH_API void ArchSetProgramInfoForErrors(const std::string &key, const std::string &value)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
ARCH_API void ArchPrintStackFrames(std::ostream &out, const std::vector< uintptr_t > &frames, bool skipUnknownFrames=false)
Print stack frames to the given ostream.
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
void(* ArchCrashHandlerSystemCB)(void *userData)
Definition: stackTrace.h:317
ARCH_API void ArchSetExtraLogInfoForErrors(const std::string &key, std::vector< std::string > const *lines)
ARCH_API std::vector< std::string > ArchGetStackTrace(size_t maxDepth)
#define ARCH_API
Definition: api.h:23
ARCH_API time_t ArchGetAppLaunchTime()
ARCH_API void ArchEnableSessionLogging()
ARCH_API std::string ArchGetProgramInfoForErrors(const std::string &key)
ARCH_API void ArchSetFatalStackLogging(bool flag)