All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
diagnosticMgr.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef TF_DIAGNOSTIC_MGR_H
25 #define TF_DIAGNOSTIC_MGR_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/base/tf/callContext.h"
31 #include "pxr/base/tf/debug.h"
32 #include "pxr/base/tf/diagnosticLite.h"
33 #include "pxr/base/tf/error.h"
34 #include "pxr/base/tf/singleton.h"
35 #include "pxr/base/tf/status.h"
36 #include "pxr/base/tf/stringUtils.h"
37 #include "pxr/base/tf/warning.h"
38 #include "pxr/base/tf/weakPtr.h"
39 #include "pxr/base/tf/enum.h"
40 #include "pxr/base/tf/api.h"
41 
42 #include "pxr/base/arch/inttypes.h"
43 #include "pxr/base/arch/attributes.h"
44 #include "pxr/base/arch/functionLite.h"
45 
46 #include <tbb/enumerable_thread_specific.h>
47 #include <tbb/spin_rw_mutex.h>
48 #include <tbb/atomic.h>
49 
50 #include <cstdarg>
51 #include <list>
52 #include <string>
53 #include <vector>
54 
55 PXR_NAMESPACE_OPEN_SCOPE
56 
58  TF_LOG_STACK_TRACE_ON_ERROR,
59  TF_ERROR_MARK_TRACKING,
60  TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR
61  );
62 
63 class TfError;
64 class TfErrorMark;
65 
70 class TfDiagnosticMgr : public TfWeakBase {
71 public:
72 
73  typedef TfDiagnosticMgr This;
74 
75  typedef std::list<TfError> ErrorList;
76 
95  typedef ErrorList::iterator ErrorIterator;
96 
98  TF_API
99  static std::string GetCodeName(const TfEnum &code);
100 
118  class Delegate {
119  public:
120  TF_API
121  virtual ~Delegate() = 0;
122 
124  virtual void IssueError(TfError const &err) = 0;
125 
128  virtual void IssueFatalError(TfCallContext const &context,
129  std::string const &msg) = 0;
130 
132  virtual void IssueStatus(TfStatus const &status) = 0;
133 
135  virtual void IssueWarning(TfWarning const &warning) = 0;
136 
137  protected:
141  TF_API
142  void _UnhandledAbort() const;
143  };
144 
146  TF_API static This &GetInstance() {
148  }
149 
157  TF_API
158  void AddDelegate(Delegate* delegate);
159 
163  TF_API
164  void RemoveDelegate(Delegate* delegate);
165 
168  TF_API
169  void SetQuiet(bool quiet) { _quiet = quiet; }
170 
172  ErrorIterator GetErrorBegin() { return _errorList.local().begin(); }
173 
175  ErrorIterator GetErrorEnd() { return _errorList.local().end(); }
176 
179  TF_API
181 
185  TF_API
187 
192  TF_API
193  void AppendError(TfError const &e);
194 
201  TF_API
202  void PostError(TfEnum errorCode, const char* errorCodeString,
203  TfCallContext const &context,
204  const std::string& commentary, TfDiagnosticInfo info,
205  bool quiet);
206 
213  TF_API
214  void PostError(const TfDiagnosticBase& diagnostic);
215 
218  TF_API
219  void PostWarning(TfEnum warningCode, const char *warningCodeString,
220  TfCallContext const &context, std::string const &commentary,
221  TfDiagnosticInfo info, bool quiet) const;
222 
225  TF_API
226  void PostWarning(const TfDiagnosticBase& diagnostic) const;
227 
230  TF_API
231  void PostStatus(TfEnum statusCode, const char *statusCodeString,
232  TfCallContext const &context, std::string const &commentary,
233  TfDiagnosticInfo info, bool quiet) const;
234 
237  TF_API
238  void PostStatus(const TfDiagnosticBase& diagnostic) const;
239 
243  TF_API
244  void PostFatal(TfCallContext const &context, TfEnum statusCode,
245  std::string const &msg) const;
246 
249  bool HasActiveErrorMark() { return _errorMarkCounts.local() > 0; }
250 
251 #if !defined(doxygen)
252  //
253  // Public, but *only* meant to be used by the TF_ERROR() macro.
254  //
256  class ErrorHelper {
257  public:
258  ErrorHelper(TfCallContext const &context, TfEnum errorCode,
259  const char* errorCodeString)
260  : _context(context), _errorCode(errorCode),
261  _errorCodeString(errorCodeString)
262  {
263  }
264 
265  TF_API
266  void Post(const char* fmt, ...) const
268 
269  TF_API
270  void PostQuietly(const char* fmt, ...) const
272 
273  TF_API
274  void Post(const std::string& msg) const;
275 
276  TF_API
277  void PostWithInfo(
278  const std::string& msg,
279  TfDiagnosticInfo info = TfDiagnosticInfo()) const;
280 
281  TF_API
282  void PostQuietly(const std::string& msg,
283  TfDiagnosticInfo info = TfDiagnosticInfo()) const;
284 
285  private:
286  TfCallContext _context;
287  TfEnum _errorCode;
288  const char *_errorCodeString;
289  };
290 
291  struct WarningHelper {
292  WarningHelper(TfCallContext const &context, TfEnum warningCode,
293  const char *warningCodeString)
294  : _context(context), _warningCode(warningCode),
295  _warningCodeString(warningCodeString)
296  {
297  }
298 
299  TF_API
300  void Post(const char* fmt, ...) const
301  ARCH_PRINTF_FUNCTION(2,3);
302 
303  TF_API
304  void PostQuietly(const char* fmt, ...) const
305  ARCH_PRINTF_FUNCTION(2,3);
306 
307  TF_API
308  void Post(const std::string &str) const;
309 
310  TF_API
311  void PostWithInfo(
312  const std::string& msg,
313  TfDiagnosticInfo info = TfDiagnosticInfo()) const;
314 
315  TF_API
316  void PostQuietly(const std::string& msg) const;
317 
318  private:
319  TfCallContext _context;
320  TfEnum _warningCode;
321  const char *_warningCodeString;
322  };
323 
324  struct StatusHelper {
325  StatusHelper(TfCallContext const &context, TfEnum statusCode,
326  const char *statusCodeString)
327  : _context(context), _statusCode(statusCode),
328  _statusCodeString(statusCodeString)
329  {
330  }
331 
332  TF_API
333  void Post(const char* fmt, ...) const
334  ARCH_PRINTF_FUNCTION(2,3);
335 
336  TF_API
337  void PostQuietly(const char* fmt, ...) const
338  ARCH_PRINTF_FUNCTION(2,3);
339 
340  TF_API
341  void Post(const std::string &str) const;
342 
343  TF_API
344  void PostWithInfo(
345  const std::string& msg,
346  TfDiagnosticInfo info = TfDiagnosticInfo()) const;
347 
348  TF_API
349  void PostQuietly(const std::string& msg) const;
350 
351  private:
352  TfCallContext _context;
353  TfEnum _statusCode;
354  const char *_statusCodeString;
355  };
356 
357  struct FatalHelper {
358  FatalHelper(TfCallContext const &context, TfEnum statusCode)
359  : _context(context),
360  _statusCode(statusCode)
361  {
362  }
363 
364  void Post(const std::string &str) const {
365  This::GetInstance().PostFatal(_context, _statusCode, str);
366  }
367  private:
368  TfCallContext _context;
369  TfEnum _statusCode;
370  };
371 
372 #endif
373 
374 private:
375 
376  TfDiagnosticMgr();
377  virtual ~TfDiagnosticMgr();
378  friend class TfSingleton<This>;
379 
380  // Return an iterator to the first error with serial number >= mark, or the
381  // past-the-end iterator, if no such errors exist.
382  TF_API
383  ErrorIterator _GetErrorMarkBegin(size_t mark, size_t *nErrors);
384 
385  // Invoked by ErrorMark ctor.
386  inline void _CreateErrorMark() { ++_errorMarkCounts.local(); }
387 
388  // Invoked by ErrorMark dtor.
389  inline bool _DestroyErrorMark() { return --_errorMarkCounts.local() == 0; }
390 
391  // Report an error, either via delegate or print to stderr, and issue a
392  // notice if this thread of execution is the main thread.
393  void _ReportError(const TfError &err);
394 
395  // Splice the errors in src into this thread's local list. Also reassign
396  // serial numbers to all the spliced errors to ensure they work correctly
397  // with local error marks.
398  void _SpliceErrors(ErrorList &src);
399 
400  // Helper to append pending error messages to the crash log.
401  void _AppendErrorsToLogText(ErrorIterator i);
402 
403  // Helper to fully rebuild the crash log error text when errors are erased
404  // from the middle.
405  void _RebuildErrorLogText();
406 
407  // Helper to actually publish log text into the Arch crash handler.
408  void _SetLogInfoForErrors(std::vector<std::string> const &logText) const;
409 
410  // A guard used to protect reentrency when adding/removing
411  // delegates as well as posting errors/warnings/statuses
412  mutable tbb::enumerable_thread_specific<bool> _reentrantGuard;
413 
414  // The registered delegates.
415  std::vector<Delegate*> _delegates;
416 
417  mutable tbb::spin_rw_mutex _delegatesMutex;
418 
419  // Global serial number for sorting.
420  tbb::atomic<size_t> _nextSerial;
421 
422  // Thread-specific error list.
423  tbb::enumerable_thread_specific<ErrorList> _errorList;
424 
425  // Thread-specific diagnostic log text for pending errors.
426  struct _LogText {
427  void AppendAndPublish(ErrorIterator i, ErrorIterator end);
428  void RebuildAndPublish(ErrorIterator i, ErrorIterator end);
429 
430  std::pair<std::vector<std::string>,
431  std::vector<std::string>> texts;
432  bool parity = false;
433  private:
434  void _AppendAndPublishImpl(bool clear,
436  };
437  tbb::enumerable_thread_specific<_LogText> _logText;
438 
439  // Thread-specific error mark counts. Use a native key for best performance
440  // here.
441  tbb::enumerable_thread_specific<
442  size_t, tbb::cache_aligned_allocator<size_t>,
443  tbb::ets_key_per_instance> _errorMarkCounts;
444 
445  bool _quiet;
446 
447  friend class TfError;
448  friend class TfErrorTransport;
449  friend class TfErrorMark;
450 };
451 
452 TF_API_TEMPLATE_CLASS(TfSingleton<TfDiagnosticMgr>);
453 
454 PXR_NAMESPACE_CLOSE_SCOPE
455 
456 #endif // TF_DIAGNOSTIC_MGR_H
Manage a single instance of an object (see.
Definition: singleton.h:122
Singleton class through which all errors and diagnostics pass.
Definition: diagnosticMgr.h:70
virtual void IssueStatus(TfStatus const &status)=0
Called when a TF_STATUS() is issued.
TF_API void PostFatal(TfCallContext const &context, TfEnum statusCode, std::string const &msg) const
If called in a non-main thread, this method will print the error msg and handle the fatal error itsel...
virtual void IssueWarning(TfWarning const &warning)=0
Called when a TF_WARNING() is issued.
TF_API void SetQuiet(bool quiet)
Set whether errors, warnings and status messages should be printed out to the terminal.
static TF_API std::string GetCodeName(const TfEnum &code)
Returns the name of the given diagnostic code.
An enum class that records both enum type and enum value.
Definition: enum.h:140
ErrorIterator GetErrorEnd()
Return an iterator to the end of this thread&#39;s error list.
static TF_API This & GetInstance()
Return the singleton instance.
#define TF_DEBUG_CODES(...)
Define debugging symbols.
Definition: debug.h:397
bool HasActiveErrorMark()
Return true if an instance of TfErrorMark exists in the current thread of execution, false otherwise.
TF_API void AddDelegate(Delegate *delegate)
Add the delegate delegate to the list of current delegates.
Represents the base class of an object representing a diagnostic message.
ErrorIterator GetErrorBegin()
Return an iterator to the beginning of this thread&#39;s error list.
TF_API ErrorIterator EraseRange(ErrorIterator first, ErrorIterator last)
Remove all the errors in [first, last) from this thread&#39;s error stream.
Class used to record the end of the error-list.
Definition: errorMark.h:66
#define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
Macro used to indicate a function takes a printf-like specification.
Definition: attributes.h:51
Represents an object that contains information about a status message.
Definition: status.h:44
TF_API void PostWarning(TfEnum warningCode, const char *warningCodeString, TfCallContext const &context, std::string const &commentary, TfDiagnosticInfo info, bool quiet) const
If called in a non-main thread, this method will print the warning msg rather than passing it to the ...
static T & GetInstance()
Return a reference to an object of type T, creating it if necessary.
Definition: singleton.h:137
TF_API ErrorIterator EraseError(ErrorIterator i)
Remove error specified by iterator i.
Represents an object that contains error information.
Definition: error.h:49
virtual void IssueError(TfError const &err)=0
Called when a TfError is posted.
TF_API void PostStatus(TfEnum statusCode, const char *statusCodeString, TfCallContext const &context, std::string const &commentary, TfDiagnosticInfo info, bool quiet) const
If called in a non-main thread, this method will print the status msg rather than passing it to the d...
TF_API void _UnhandledAbort() const
Abort the program, but avoid the session logging mechanism.
TF_API void PostError(TfEnum errorCode, const char *errorCodeString, TfCallContext const &context, const std::string &commentary, TfDiagnosticInfo info, bool quiet)
If called in a main thread, this method will create a TfError, append it to the error list...
TF_API void RemoveDelegate(Delegate *delegate)
Removes all delegates equal to delegate from the current delegates.
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:142
Represents an object that contains information about a warning.
Definition: warning.h:44
ErrorList::iterator ErrorIterator
Synonym for standard STL iterator to traverse the error list.
Definition: diagnosticMgr.h:95
One may set a delegate with the TfDiagnosticMgr which will be called to respond to errors and diagnos...
virtual void IssueFatalError(TfCallContext const &context, std::string const &msg)=0
Called when a TF_FATAL_ERROR is issued (or a failed TF_AXIOM).
A facility for transporting errors from thread to thread.
TF_API void AppendError(TfError const &e)
Append an error to the list of active errors.