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 PXR_BASE_TF_DIAGNOSTIC_MGR_H
25 #define PXR_BASE_TF_DIAGNOSTIC_MGR_H
26 
28 
29 #include "pxr/pxr.h"
31 #include "pxr/base/tf/debug.h"
33 #include "pxr/base/tf/error.h"
34 #include "pxr/base/tf/singleton.h"
35 #include "pxr/base/tf/status.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"
45 
46 #include <tbb/enumerable_thread_specific.h>
47 #include <tbb/spin_rw_mutex.h>
48 
49 #include <atomic>
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_LOG_STACK_TRACE_ON_WARNING,
60  TF_ERROR_MARK_TRACKING,
61  TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR
62  );
63 
64 class TfError;
65 class TfErrorMark;
66 
71 class TfDiagnosticMgr : public TfWeakBase {
72 public:
73 
74  typedef TfDiagnosticMgr This;
75 
76  typedef std::list<TfError> ErrorList;
77 
96  typedef ErrorList::iterator ErrorIterator;
97 
99  TF_API
100  static std::string GetCodeName(const TfEnum &code);
101 
106  TF_API
107  static std::string FormatDiagnostic(const TfEnum &code,
108  const TfCallContext &context, const std::string &msg,
109  const TfDiagnosticInfo &info);
110 
128  class Delegate {
129  public:
130  TF_API
131  virtual ~Delegate() = 0;
132 
134  virtual void IssueError(TfError const &err) = 0;
135 
138  virtual void IssueFatalError(TfCallContext const &context,
139  std::string const &msg) = 0;
140 
142  virtual void IssueStatus(TfStatus const &status) = 0;
143 
145  virtual void IssueWarning(TfWarning const &warning) = 0;
146 
147  protected:
151  TF_API
152  void _UnhandledAbort() const;
153  };
154 
156  TF_API static This &GetInstance() {
158  }
159 
167  TF_API
168  void AddDelegate(Delegate* delegate);
169 
173  TF_API
174  void RemoveDelegate(Delegate* delegate);
175 
178  TF_API
179  void SetQuiet(bool quiet) { _quiet = quiet; }
180 
182  ErrorIterator GetErrorBegin() { return _errorList.local().begin(); }
183 
185  ErrorIterator GetErrorEnd() { return _errorList.local().end(); }
186 
189  TF_API
191 
195  TF_API
197 
202  TF_API
203  void AppendError(TfError const &e);
204 
210  TF_API
211  void PostError(TfEnum errorCode, const char* errorCodeString,
212  TfCallContext const &context,
213  const std::string& commentary, TfDiagnosticInfo info,
214  bool quiet);
215 
221  TF_API
222  void PostError(const TfDiagnosticBase& diagnostic);
223 
228  TF_API
229  void PostWarning(TfEnum warningCode, const char *warningCodeString,
230  TfCallContext const &context, std::string const &commentary,
231  TfDiagnosticInfo info, bool quiet) const;
232 
237  TF_API
238  void PostWarning(const TfDiagnosticBase& diagnostic) const;
239 
244  TF_API
245  void PostStatus(TfEnum statusCode, const char *statusCodeString,
246  TfCallContext const &context, std::string const &commentary,
247  TfDiagnosticInfo info, bool quiet) const;
248 
253  TF_API
254  void PostStatus(const TfDiagnosticBase& diagnostic) const;
255 
260  TF_API
261  void PostFatal(TfCallContext const &context, TfEnum statusCode,
262  std::string const &msg) const;
263 
266  bool HasActiveErrorMark() { return _errorMarkCounts.local() > 0; }
267 
268 #if !defined(doxygen)
269  //
270  // Public, but *only* meant to be used by the TF_ERROR() macro.
271  //
273  class ErrorHelper {
274  public:
275  ErrorHelper(TfCallContext const &context, TfEnum errorCode,
276  const char* errorCodeString)
277  : _context(context), _errorCode(errorCode),
278  _errorCodeString(errorCodeString)
279  {
280  }
281 
282  TF_API
283  void Post(const char* fmt, ...) const
285 
286  TF_API
287  void PostQuietly(const char* fmt, ...) const
289 
290  TF_API
291  void Post(const std::string& msg) const;
292 
293  TF_API
294  void PostWithInfo(
295  const std::string& msg,
296  TfDiagnosticInfo info = TfDiagnosticInfo()) const;
297 
298  TF_API
299  void PostQuietly(const std::string& msg,
300  TfDiagnosticInfo info = TfDiagnosticInfo()) const;
301 
302  private:
303  TfCallContext _context;
304  TfEnum _errorCode;
305  const char *_errorCodeString;
306  };
307 
308  struct WarningHelper {
309  WarningHelper(TfCallContext const &context, TfEnum warningCode,
310  const char *warningCodeString)
311  : _context(context), _warningCode(warningCode),
312  _warningCodeString(warningCodeString)
313  {
314  }
315 
316  TF_API
317  void Post(const char* fmt, ...) const
319 
320  TF_API
321  void PostQuietly(const char* fmt, ...) const
323 
324  TF_API
325  void Post(const std::string &str) const;
326 
327  TF_API
328  void PostWithInfo(
329  const std::string& msg,
330  TfDiagnosticInfo info = TfDiagnosticInfo()) const;
331 
332  TF_API
333  void PostQuietly(const std::string& msg) const;
334 
335  private:
336  TfCallContext _context;
337  TfEnum _warningCode;
338  const char *_warningCodeString;
339  };
340 
341  struct StatusHelper {
342  StatusHelper(TfCallContext const &context, TfEnum statusCode,
343  const char *statusCodeString)
344  : _context(context), _statusCode(statusCode),
345  _statusCodeString(statusCodeString)
346  {
347  }
348 
349  TF_API
350  void Post(const char* fmt, ...) const
352 
353  TF_API
354  void PostQuietly(const char* fmt, ...) const
356 
357  TF_API
358  void Post(const std::string &str) const;
359 
360  TF_API
361  void PostWithInfo(
362  const std::string& msg,
363  TfDiagnosticInfo info = TfDiagnosticInfo()) const;
364 
365  TF_API
366  void PostQuietly(const std::string& msg) const;
367 
368  private:
369  TfCallContext _context;
370  TfEnum _statusCode;
371  const char *_statusCodeString;
372  };
373 
374  struct FatalHelper {
375  FatalHelper(TfCallContext const &context, TfEnum statusCode)
376  : _context(context),
377  _statusCode(statusCode)
378  {
379  }
380 
381  void Post(const std::string &str) const {
382  This::GetInstance().PostFatal(_context, _statusCode, str);
383  }
384  private:
385  TfCallContext _context;
386  TfEnum _statusCode;
387  };
388 
389 #endif
390 
391 private:
392 
393  TfDiagnosticMgr();
394  virtual ~TfDiagnosticMgr();
395  friend class TfSingleton<This>;
396 
397  // Return an iterator to the first error with serial number >= mark, or the
398  // past-the-end iterator, if no such errors exist.
399  TF_API
400  ErrorIterator _GetErrorMarkBegin(size_t mark, size_t *nErrors);
401 
402  // Invoked by ErrorMark ctor.
403  inline void _CreateErrorMark() { ++_errorMarkCounts.local(); }
404 
405  // Invoked by ErrorMark dtor.
406  inline bool _DestroyErrorMark() { return --_errorMarkCounts.local() == 0; }
407 
408  // Report an error, either via delegate or print to stderr, and issue a
409  // notice if this thread of execution is the main thread.
410  void _ReportError(const TfError &err);
411 
412  // Splice the errors in src into this thread's local list. Also reassign
413  // serial numbers to all the spliced errors to ensure they work correctly
414  // with local error marks.
415  void _SpliceErrors(ErrorList &src);
416 
417  // Helper to append pending error messages to the crash log.
418  void _AppendErrorsToLogText(ErrorIterator i);
419 
420  // Helper to fully rebuild the crash log error text when errors are erased
421  // from the middle.
422  void _RebuildErrorLogText();
423 
424  // Helper to actually publish log text into the Arch crash handler.
425  void _SetLogInfoForErrors(std::vector<std::string> const &logText) const;
426 
427  // A guard used to protect reentrency when adding/removing
428  // delegates as well as posting errors/warnings/statuses
429  mutable tbb::enumerable_thread_specific<bool> _reentrantGuard;
430 
431  // The registered delegates.
432  std::vector<Delegate*> _delegates;
433 
434  mutable tbb::spin_rw_mutex _delegatesMutex;
435 
436  // Global serial number for sorting.
437  std::atomic<size_t> _nextSerial;
438 
439  // Thread-specific error list.
440  tbb::enumerable_thread_specific<ErrorList> _errorList;
441 
442  // Thread-specific diagnostic log text for pending errors.
443  struct _LogText {
444  void AppendAndPublish(ErrorIterator i, ErrorIterator end);
445  void RebuildAndPublish(ErrorIterator i, ErrorIterator end);
446 
447  std::pair<std::vector<std::string>,
448  std::vector<std::string>> texts;
449  bool parity = false;
450  private:
451  void _AppendAndPublishImpl(bool clear,
453  };
454  tbb::enumerable_thread_specific<_LogText> _logText;
455 
456  // Thread-specific error mark counts. Use a native key for best performance
457  // here.
458  tbb::enumerable_thread_specific<
459  size_t, tbb::cache_aligned_allocator<size_t>,
460  tbb::ets_key_per_instance> _errorMarkCounts;
461 
462  bool _quiet;
463 
464  friend class TfError;
465  friend class TfErrorTransport;
466  friend class TfErrorMark;
467 };
468 
469 TF_API_TEMPLATE_CLASS(TfSingleton<TfDiagnosticMgr>);
470 
471 PXR_NAMESPACE_CLOSE_SCOPE
472 
473 #endif // PXR_BASE_TF_DIAGNOSTIC_MGR_H
Manage a single instance of an object.
Manage a single instance of an object (see.
Definition: singleton.h:122
Singleton class through which all errors and diagnostics pass.
Definition: diagnosticMgr.h:71
virtual void IssueStatus(TfStatus const &status)=0
Called when a TF_STATUS() is issued.
Functions for recording call locations.
Conditional debugging output class and macros.
Define preprocessor function name macros.
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.
Define function attributes.
static TF_API std::string GetCodeName(const TfEnum &code)
Returns the name of the given diagnostic code.
Definitions of basic string utilities in tf.
An enum class that records both enum type and enum value.
Definition: enum.h:139
ErrorIterator GetErrorEnd()
Return an iterator to the end of this thread's error list.
static TF_API This & GetInstance()
Return the singleton instance.
Pointer storage with deletion detection.
static TF_API std::string FormatDiagnostic(const TfEnum &code, const TfCallContext &context, const std::string &msg, const TfDiagnosticInfo &info)
Return a human-readable diagnostic message.
#define TF_DEBUG_CODES(...)
Define debugging symbols.
Definition: debug.h:393
bool HasActiveErrorMark()
Return true if an instance of TfErrorMark exists in the current thread of execution,...
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's error list.
TF_API ErrorIterator EraseRange(ErrorIterator first, ErrorIterator last)
Remove all the errors in [first, last) from this thread'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
TF_API void PostWarning(TfEnum warningCode, const char *warningCodeString, TfCallContext const &context, std::string const &commentary, TfDiagnosticInfo info, bool quiet) const
This method will create a TfWarning and pass it to all delegates.
Represents an object that contains information about a status message.
Definition: status.h:44
TF_API void _UnhandledAbort() const
Abort the program, but avoid the session logging mechanism.
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
Define integral types.
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
This method will create a TfStatus and pass it to all delegates.
TF_API void PostError(TfEnum errorCode, const char *errorCodeString, TfCallContext const &context, const std::string &commentary, TfDiagnosticInfo info, bool quiet)
This method will create a TfError, append it to the error list, and pass it to all delegates.
TF_API void RemoveDelegate(Delegate *delegate)
Removes all delegates equal to delegate from the current delegates.
TF_API void PostFatal(TfCallContext const &context, TfEnum statusCode, std::string const &msg) const
This method will issue a fatal error to all delegates.
Provide facilities for error handling in script.
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:141
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:96
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.
Stripped down version of diagnostic.h that doesn't define std::string.