PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/runtime/ext/ext_error.cpp

https://github.com/tstarling/hiphop-php
C++ | 251 lines | 196 code | 23 blank | 32 comment | 28 complexity | 798b3f288db76a4a628aadbcafe1e528 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
  6. | Copyright (c) 1997-2010 The PHP Group |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 3.01 of the PHP license, |
  9. | that is bundled with this package in the file LICENSE, and is |
  10. | available through the world-wide-web at the following url: |
  11. | http://www.php.net/license/3_01.txt |
  12. | If you did not receive a copy of the PHP license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@php.net so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. */
  17. #include "hphp/runtime/ext/ext_error.h"
  18. #include <iostream>
  19. #include "hphp/runtime/base/exceptions.h"
  20. #include "hphp/runtime/base/string-buffer.h"
  21. #include "hphp/runtime/base/thread-info.h"
  22. #include "hphp/runtime/ext/ext_file.h"
  23. #include "hphp/util/logger.h"
  24. namespace HPHP {
  25. ///////////////////////////////////////////////////////////////////////////////
  26. const int DEBUG_BACKTRACE_PROVIDE_OBJECT = 1;
  27. const int DEBUG_BACKTRACE_IGNORE_ARGS = 2;
  28. Array f_debug_backtrace(int64_t options /* = 1 */, int64_t limit /* = 0 */) {
  29. bool provide_object = options & DEBUG_BACKTRACE_PROVIDE_OBJECT;
  30. bool ignore_args = options & DEBUG_BACKTRACE_IGNORE_ARGS;
  31. return g_context->debugBacktrace(
  32. true, false, provide_object, nullptr, ignore_args, limit
  33. );
  34. }
  35. /**
  36. * hphp_debug_caller_info - returns an array of info about the "caller"
  37. *
  38. * For clarity, we refer to the function that called hphp_debug_caller_info()
  39. * as the "callee", and we refer to the function that called the callee as
  40. * the "caller".
  41. *
  42. * This function returns an array containing two keys "file" and "line" which
  43. * indicate the the filename and line number where the "caller" called the
  44. * "callee".
  45. */
  46. Array f_hphp_debug_caller_info() {
  47. if (RuntimeOption::InjectedStackTrace) {
  48. return g_context->getCallerInfo();
  49. }
  50. return Array::Create();
  51. }
  52. void f_debug_print_backtrace(int64_t options /* = 0 */,
  53. int64_t limit /* = 0 */) {
  54. bool ignore_args = options & DEBUG_BACKTRACE_IGNORE_ARGS;
  55. echo(debug_string_backtrace(true, ignore_args, limit));
  56. }
  57. const StaticString
  58. s_class("class"),
  59. s_type("type"),
  60. s_function("function"),
  61. s_file("file"),
  62. s_line("line"),
  63. s_message("message"),
  64. s_args("args");
  65. String debug_string_backtrace(bool skip, bool ignore_args /* = false */,
  66. int limit /* = 0 */) {
  67. if (RuntimeOption::InjectedStackTrace) {
  68. Array bt;
  69. StringBuffer buf;
  70. bt = g_context->debugBacktrace(skip, false, false, nullptr,
  71. ignore_args, limit);
  72. int i = 0;
  73. for (ArrayIter it = bt.begin(); !it.end(); it.next(), i++) {
  74. Array frame = it.second().toArray();
  75. buf.append('#');
  76. buf.append(i);
  77. if (i < 10) buf.append(' ');
  78. buf.append(' ');
  79. if (frame.exists(s_class)) {
  80. buf.append(frame->get(s_class).toString());
  81. buf.append(frame->get(s_type).toString());
  82. }
  83. buf.append(frame->get(s_function).toString());
  84. buf.append("(");
  85. if (!ignore_args) {
  86. bool first = true;
  87. for (ArrayIter it(frame->get(s_args).toArray());
  88. !it.end();
  89. it.next()) {
  90. if (!first) {
  91. buf.append(", ");
  92. } else {
  93. first = false;
  94. }
  95. try {
  96. buf.append(it.second().toString());
  97. } catch (FatalErrorException& fe) {
  98. buf.append(fe.getMessage());
  99. }
  100. }
  101. }
  102. buf.append(")");
  103. if (frame.exists(s_file)) {
  104. buf.append(" called at [");
  105. buf.append(frame->get(s_file).toString());
  106. buf.append(':');
  107. buf.append(frame->get(s_line).toString());
  108. buf.append(']');
  109. }
  110. buf.append('\n');
  111. }
  112. return buf.detach();
  113. } else {
  114. StackTrace st;
  115. return String(st.toString());
  116. }
  117. }
  118. Array f_error_get_last() {
  119. String lastError = g_context->getLastError();
  120. if (lastError.isNull()) {
  121. return (ArrayData *)NULL;
  122. }
  123. return make_map_array(s_type, g_context->getLastErrorNumber(),
  124. s_message, g_context->getLastError(),
  125. s_file, g_context->getLastErrorPath(),
  126. s_line, g_context->getLastErrorLine());
  127. }
  128. bool f_error_log(const String& message, int message_type /* = 0 */,
  129. const String& destination /* = null_string */,
  130. const String& extra_headers /* = null_string */) {
  131. // error_log() should not invoke the user error handler,
  132. // so we use Logger::Error() instead of raise_warning() or raise_error()
  133. switch (message_type) {
  134. case 0:
  135. {
  136. std::string line(message.data(),
  137. // Truncate to 512k
  138. message.size() > (1<<19) ? (1<<19) : message.size());
  139. Logger::Error(line);
  140. return true;
  141. }
  142. case 3:
  143. {
  144. Variant outfile = f_fopen(destination, "a"); // open for append only
  145. if (outfile.isNull()) {
  146. Logger::Error("can't open error_log file!\n");
  147. return false;
  148. }
  149. f_fwrite(outfile.toResource(), message);
  150. f_fclose(outfile.toResource());
  151. return true;
  152. }
  153. case 2: // not used per PHP
  154. default:
  155. Logger::Error("error_log does not support message_type %d!", message_type);
  156. break;
  157. }
  158. return false;
  159. }
  160. int64_t f_error_reporting(const Variant& level /* = null */) {
  161. auto& id = ThreadInfo::s_threadInfo.getNoCheck()->m_reqInjectionData;
  162. int oldErrorReportingLevel = id.getErrorReportingLevel();
  163. if (!level.isNull()) {
  164. id.setErrorReportingLevel(level.toInt32());
  165. }
  166. return oldErrorReportingLevel;
  167. }
  168. bool f_restore_error_handler() {
  169. g_context->popUserErrorHandler();
  170. return true;
  171. }
  172. bool f_restore_exception_handler() {
  173. g_context->popUserExceptionHandler();
  174. return false;
  175. }
  176. Variant f_set_error_handler(const Variant& error_handler,
  177. int error_types /* = k_E_ALL */) {
  178. return g_context->pushUserErrorHandler(error_handler, error_types);
  179. }
  180. Variant f_set_exception_handler(const Variant& exception_handler) {
  181. return g_context->pushUserExceptionHandler(exception_handler);
  182. }
  183. void f_hphp_set_error_page(const String& page) {
  184. g_context->setErrorPage(page);
  185. }
  186. void f_hphp_throw_fatal_error(const String& error_msg) {
  187. std::string msg = error_msg.data();
  188. raise_error(msg);
  189. }
  190. void f_hphp_clear_unflushed() {
  191. g_context->obEndAll();
  192. g_context->obStart();
  193. g_context->obProtect(true);
  194. }
  195. bool f_trigger_error(const String& error_msg,
  196. int error_type /* = k_E_USER_NOTICE */) {
  197. std::string msg = error_msg.data();
  198. if (g_context->getThrowAllErrors()) throw error_type;
  199. if (error_type == k_E_USER_ERROR) {
  200. g_context->handleError(msg, error_type, true,
  201. ExecutionContext::ErrorThrowMode::IfUnhandled,
  202. "HipHop Recoverable error: ");
  203. } else if (error_type == k_E_USER_WARNING) {
  204. g_context->handleError(msg, error_type, true,
  205. ExecutionContext::ErrorThrowMode::Never,
  206. "\nWarning: ");
  207. } else if (error_type == k_E_USER_NOTICE) {
  208. g_context->handleError(msg, error_type, true,
  209. ExecutionContext::ErrorThrowMode::Never,
  210. "\nNotice: ");
  211. } else if (error_type == k_E_USER_DEPRECATED) {
  212. g_context->handleError(msg, error_type, true,
  213. ExecutionContext::ErrorThrowMode::Never,
  214. "HipHop Deprecated: ");
  215. } else {
  216. raise_warning("Invalid error type specified");
  217. return false;
  218. }
  219. return true;
  220. }
  221. bool f_user_error(const String& error_msg,
  222. int error_type /* = k_E_USER_NOTICE */) {
  223. return f_trigger_error(error_msg, error_type);
  224. }
  225. const int64_t k_DEBUG_BACKTRACE_PROVIDE_OBJECT = 1;
  226. const int64_t k_DEBUG_BACKTRACE_IGNORE_ARGS = 2;
  227. ///////////////////////////////////////////////////////////////////////////////
  228. }