traceback.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. #ifdef __gnu_linux__
  2. # include <sys/prctl.h>
  3. #endif
  4. #include "Python.h"
  5. #include <frameobject.h>
  6. #if PY_MAJOR_VERSION >= 3
  7. # define PYSTRING_CHECK PyUnicode_Check
  8. #else
  9. # define PYSTRING_CHECK PyString_Check
  10. #endif
  11. #define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
  12. #define MAX_STRING_LENGTH 500
  13. #define MAX_FRAME_DEPTH 100
  14. #define MAX_NTHREADS 100
  15. /* Write count bytes of buf into fd.
  16. *
  17. * On success, return the number of written bytes, it can be lower than count
  18. * including 0. On error, set errno and return -1.
  19. *
  20. * When interrupted by a signal (write() fails with EINTR), retry the syscall
  21. * without calling the Python signal handler. */
  22. Py_ssize_t
  23. _Py_write_noraise(int fd, const char *buf, size_t count)
  24. {
  25. Py_ssize_t res;
  26. do {
  27. #ifdef MS_WINDOWS
  28. assert(count < INT_MAX);
  29. res = write(fd, buf, (int)count);
  30. #else
  31. res = write(fd, buf, count);
  32. #endif
  33. /* retry write() if it was interrupted by a signal */
  34. } while (res < 0 && errno == EINTR);
  35. return res;
  36. }
  37. /* Reverse a string. For example, "abcd" becomes "dcba".
  38. This function is signal safe. */
  39. void
  40. reverse_string(char *text, const size_t len)
  41. {
  42. char tmp;
  43. size_t i, j;
  44. if (len == 0)
  45. return;
  46. for (i=0, j=len-1; i < j; i++, j--) {
  47. tmp = text[i];
  48. text[i] = text[j];
  49. text[j] = tmp;
  50. }
  51. }
  52. /* Format an integer in range [0; 999999999] to decimal,
  53. and write it into the file fd.
  54. This function is signal safe. */
  55. void
  56. dump_decimal(int fd, int value)
  57. {
  58. char buffer[10];
  59. int len;
  60. if (value < 0 || 999999999 < value)
  61. return;
  62. len = 0;
  63. do {
  64. buffer[len] = '0' + (value % 10);
  65. value /= 10;
  66. len++;
  67. } while (value);
  68. reverse_string(buffer, len);
  69. _Py_write_noraise(fd, buffer, len);
  70. }
  71. /* Format an integer in range [0; 0xffffffff] to hexadecimal of 'width' digits,
  72. and write it into the file fd.
  73. This function is signal safe. */
  74. void
  75. _Py_dump_hexadecimal(int fd, unsigned long value, size_t bytes)
  76. {
  77. const char *hexdigits = "0123456789abcdef";
  78. size_t width = bytes * 2;
  79. size_t len;
  80. char buffer[sizeof(unsigned long) * 2 + 1];
  81. len = 0;
  82. do {
  83. buffer[len] = hexdigits[value & 15];
  84. value >>= 4;
  85. len++;
  86. } while (len < width || value);
  87. reverse_string(buffer, len);
  88. _Py_write_noraise(fd, buffer, len);
  89. }
  90. /* Write an unicode object into the file fd using ascii+backslashreplace.
  91. This function is signal safe. */
  92. static void
  93. dump_ascii(int fd, PyObject *text)
  94. {
  95. Py_ssize_t i, size;
  96. int truncated;
  97. unsigned long ch;
  98. #if PY_MAJOR_VERSION >= 3
  99. Py_UNICODE *u;
  100. size = PyUnicode_GET_SIZE(text);
  101. u = PyUnicode_AS_UNICODE(text);
  102. #else
  103. char *s;
  104. size = PyString_GET_SIZE(text);
  105. s = PyString_AS_STRING(text);
  106. #endif
  107. if (MAX_STRING_LENGTH < size) {
  108. size = MAX_STRING_LENGTH;
  109. truncated = 1;
  110. }
  111. else
  112. truncated = 0;
  113. #if PY_MAJOR_VERSION >= 3
  114. for (i=0; i < size; i++, u++) {
  115. ch = *u;
  116. if (' ' <= ch && ch < 0x7f) {
  117. /* printable ASCII character */
  118. char c = (char)ch;
  119. _Py_write_noraise(fd, &c, 1);
  120. }
  121. else if (ch <= 0xff) {
  122. PUTS(fd, "\\x");
  123. _Py_dump_hexadecimal(fd, ch, 1);
  124. }
  125. else
  126. #ifdef Py_UNICODE_WIDE
  127. if (ch <= 0xffff)
  128. #endif
  129. {
  130. PUTS(fd, "\\u");
  131. _Py_dump_hexadecimal(fd, ch, 2);
  132. #ifdef Py_UNICODE_WIDE
  133. }
  134. else {
  135. PUTS(fd, "\\U");
  136. _Py_dump_hexadecimal(fd, ch, 4);
  137. #endif
  138. }
  139. }
  140. #else
  141. for (i=0; i < size; i++, s++) {
  142. ch = *s;
  143. if (' ' <= ch && ch <= 126) {
  144. /* printable ASCII character */
  145. _Py_write_noraise(fd, s, 1);
  146. }
  147. else {
  148. PUTS(fd, "\\x");
  149. _Py_dump_hexadecimal(fd, ch, 1);
  150. }
  151. }
  152. #endif
  153. if (truncated)
  154. PUTS(fd, "...");
  155. }
  156. /* Write a frame into the file fd: "File "xxx", line xxx in xxx".
  157. This function is signal safe. */
  158. static void
  159. dump_frame(int fd, PyFrameObject *frame)
  160. {
  161. PyCodeObject *code;
  162. int lineno;
  163. code = frame->f_code;
  164. PUTS(fd, " File ");
  165. if (code != NULL && code->co_filename != NULL
  166. && PYSTRING_CHECK(code->co_filename))
  167. {
  168. PUTS(fd, "\"");
  169. dump_ascii(fd, code->co_filename);
  170. PUTS(fd, "\"");
  171. } else {
  172. PUTS(fd, "???");
  173. }
  174. #if (PY_MAJOR_VERSION <= 2 && PY_MINOR_VERSION < 7) \
  175. || (PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION < 2)
  176. /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */
  177. lineno = PyCode_Addr2Line(code, frame->f_lasti);
  178. #else
  179. lineno = PyFrame_GetLineNumber(frame);
  180. #endif
  181. PUTS(fd, ", line ");
  182. dump_decimal(fd, lineno);
  183. PUTS(fd, " in ");
  184. if (code != NULL && code->co_name != NULL
  185. && PYSTRING_CHECK(code->co_name))
  186. dump_ascii(fd, code->co_name);
  187. else
  188. PUTS(fd, "???");
  189. PUTS(fd, "\n");
  190. }
  191. static void
  192. dump_traceback(int fd, PyThreadState *tstate, int write_header)
  193. {
  194. PyFrameObject *frame;
  195. unsigned int depth;
  196. if (write_header)
  197. PUTS(fd, "Stack (most recent call first):\n");
  198. frame = _PyThreadState_GetFrame(tstate);
  199. if (frame == NULL)
  200. return;
  201. depth = 0;
  202. while (frame != NULL) {
  203. if (MAX_FRAME_DEPTH <= depth) {
  204. PUTS(fd, " ...\n");
  205. break;
  206. }
  207. if (!PyFrame_Check(frame))
  208. break;
  209. dump_frame(fd, frame);
  210. frame = frame->f_back;
  211. depth++;
  212. }
  213. }
  214. /* Dump the traceback of a Python thread into fd. Use write() to write the
  215. traceback and retry if write() is interrupted by a signal (failed with
  216. EINTR), but don't call the Python signal handler.
  217. The caller is responsible to call PyErr_CheckSignals() to call Python signal
  218. handlers if signals were received. */
  219. void
  220. _Py_DumpTraceback(int fd, PyThreadState *tstate)
  221. {
  222. dump_traceback(fd, tstate, 1);
  223. }
  224. /* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
  225. is_current is true, "Thread 0xHHHH:\n" otherwise.
  226. This function is signal safe. */
  227. static void
  228. write_thread_id(int fd, PyThreadState *tstate, int is_current)
  229. {
  230. if (is_current)
  231. PUTS(fd, "Current thread 0x");
  232. else
  233. PUTS(fd, "Thread 0x");
  234. _Py_dump_hexadecimal(fd, (unsigned long)tstate->thread_id, sizeof(unsigned long));
  235. #ifdef __gnu_linux__
  236. /* Linux only, get and print thread name */
  237. static char thread_name[16];
  238. if (0 == prctl(PR_GET_NAME, (unsigned long) thread_name, 0, 0, 0)) {
  239. if (0 != strlen(thread_name)) {
  240. PUTS(fd, " <");
  241. PUTS(fd, thread_name);
  242. PUTS(fd, ">");
  243. }
  244. }
  245. #endif
  246. PUTS(fd, " (most recent call first):\n");
  247. }
  248. /* Dump the traceback of all Python threads into fd. Use write() to write the
  249. traceback and retry if write() is interrupted by a signal (failed with
  250. EINTR), but don't call the Python signal handler.
  251. The caller is responsible to call PyErr_CheckSignals() to call Python signal
  252. handlers if signals were received. */
  253. const char*
  254. _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
  255. PyThreadState *current_thread)
  256. {
  257. PyThreadState *tstate;
  258. unsigned int nthreads;
  259. /* Get the current interpreter from the current thread */
  260. tstate = PyInterpreterState_ThreadHead(interp);
  261. if (tstate == NULL)
  262. return "unable to get the thread head state";
  263. /* Dump the traceback of each thread */
  264. tstate = PyInterpreterState_ThreadHead(interp);
  265. nthreads = 0;
  266. do
  267. {
  268. if (nthreads != 0)
  269. PUTS(fd, "\n");
  270. if (nthreads >= MAX_NTHREADS) {
  271. PUTS(fd, "...\n");
  272. break;
  273. }
  274. write_thread_id(fd, tstate, tstate == current_thread);
  275. dump_traceback(fd, tstate, 0);
  276. tstate = PyThreadState_Next(tstate);
  277. nthreads++;
  278. } while (tstate != NULL);
  279. return NULL;
  280. }