error.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2000 by authors.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #ifdef _WIN32
  22. #define WIN32_LEAN_AND_MEAN
  23. #include <windows.h>
  24. #endif
  25. #include <atomic>
  26. #include <csignal>
  27. #include <cstdarg>
  28. #include <cstdio>
  29. #include <cstring>
  30. #include <mutex>
  31. #include "AL/al.h"
  32. #include "AL/alc.h"
  33. #include "alcontext.h"
  34. #include "alexcpt.h"
  35. #include "almalloc.h"
  36. #include "event.h"
  37. #include "inprogext.h"
  38. #include "logging.h"
  39. #include "opthelpers.h"
  40. #include "vector.h"
  41. bool TrapALError{false};
  42. void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
  43. {
  44. auto message = al::vector<char>(256);
  45. va_list args, args2;
  46. va_start(args, msg);
  47. va_copy(args2, args);
  48. int msglen{std::vsnprintf(message.data(), message.size(), msg, args)};
  49. if(msglen >= 0 && static_cast<size_t>(msglen) >= message.size())
  50. {
  51. message.resize(static_cast<size_t>(msglen) + 1u);
  52. msglen = std::vsnprintf(message.data(), message.size(), msg, args2);
  53. }
  54. va_end(args2);
  55. va_end(args);
  56. if(msglen >= 0) msg = message.data();
  57. else msg = "<internal error constructing message>";
  58. msglen = static_cast<int>(strlen(msg));
  59. WARN("Error generated on context %p, code 0x%04x, \"%s\"\n",
  60. decltype(std::declval<void*>()){this}, errorCode, msg);
  61. if(TrapALError)
  62. {
  63. #ifdef _WIN32
  64. /* DebugBreak will cause an exception if there is no debugger */
  65. if(IsDebuggerPresent())
  66. DebugBreak();
  67. #elif defined(SIGTRAP)
  68. raise(SIGTRAP);
  69. #endif
  70. }
  71. ALenum curerr{AL_NO_ERROR};
  72. mLastError.compare_exchange_strong(curerr, errorCode);
  73. if((mEnabledEvts.load(std::memory_order_relaxed)&EventType_Error))
  74. {
  75. std::lock_guard<std::mutex> _{mEventCbLock};
  76. ALbitfieldSOFT enabledevts{mEnabledEvts.load(std::memory_order_relaxed)};
  77. if((enabledevts&EventType_Error) && mEventCb)
  78. (*mEventCb)(AL_EVENT_TYPE_ERROR_SOFT, 0, static_cast<ALuint>(errorCode), msglen, msg,
  79. mEventParam);
  80. }
  81. }
  82. AL_API ALenum AL_APIENTRY alGetError(void)
  83. START_API_FUNC
  84. {
  85. ContextRef context{GetContextRef()};
  86. if UNLIKELY(!context)
  87. {
  88. constexpr ALenum deferror{AL_INVALID_OPERATION};
  89. WARN("Querying error state on null context (implicitly 0x%04x)\n", deferror);
  90. if(TrapALError)
  91. {
  92. #ifdef _WIN32
  93. if(IsDebuggerPresent())
  94. DebugBreak();
  95. #elif defined(SIGTRAP)
  96. raise(SIGTRAP);
  97. #endif
  98. }
  99. return deferror;
  100. }
  101. return context->mLastError.exchange(AL_NO_ERROR);
  102. }
  103. END_API_FUNC