diff options
| author | Gemini Lasswell | 2018-08-09 14:21:57 -0700 |
|---|---|---|
| committer | Gemini Lasswell | 2018-09-09 07:41:49 -0700 |
| commit | 3fb8f306475a87a30a7dd68387d8da859cffc90a (patch) | |
| tree | 8d8f600a2bae48e351a7424648ef100d402ae261 /src | |
| parent | dc5c76c37488d6fd546eefb33cea1edf4d13859e (diff) | |
| download | emacs-3fb8f306475a87a30a7dd68387d8da859cffc90a.tar.gz emacs-3fb8f306475a87a30a7dd68387d8da859cffc90a.zip | |
Show backtraces of threads from thread list buffer
* src/eval.c (backtrace_thread_p, backtrace_thread_top)
(backtrace_thread_next, Fbacktrace_frames_from_thread): New functions.
* lisp/thread.el (thread-list-mode-map): Add keybinding and
menu item for 'thread-list-pop-to-backtrace'.
(thread-list-mode): Make "Thread Name" column wide enough
for the result of printing a thread with no name with 'prin1'.
(thread-list--get-entries): Use 'thread-list--name'.
(thread-list--send-signal): Remove unnecessary calls to 'threadp'.
(thread-list-backtrace--thread): New variable.
(thread-list-pop-to-backtrace): New command.
(thread-list-backtrace--revert-hook-function)
(thread-list--make-backtrace-frame)
(thread-list-backtrace--insert-header, thread-list--name): New
functions.
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/eval.c b/src/eval.c index 1011fc888b5..60dd6f1e8d2 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -204,6 +204,10 @@ bool | |||
| 204 | backtrace_p (union specbinding *pdl) | 204 | backtrace_p (union specbinding *pdl) |
| 205 | { return pdl >= specpdl; } | 205 | { return pdl >= specpdl; } |
| 206 | 206 | ||
| 207 | static bool | ||
| 208 | backtrace_thread_p (struct thread_state *tstate, union specbinding *pdl) | ||
| 209 | { return pdl >= tstate->m_specpdl; } | ||
| 210 | |||
| 207 | union specbinding * | 211 | union specbinding * |
| 208 | backtrace_top (void) | 212 | backtrace_top (void) |
| 209 | { | 213 | { |
| @@ -213,6 +217,15 @@ backtrace_top (void) | |||
| 213 | return pdl; | 217 | return pdl; |
| 214 | } | 218 | } |
| 215 | 219 | ||
| 220 | static union specbinding * | ||
| 221 | backtrace_thread_top (struct thread_state *tstate) | ||
| 222 | { | ||
| 223 | union specbinding *pdl = tstate->m_specpdl_ptr - 1; | ||
| 224 | while (backtrace_thread_p (tstate, pdl) && pdl->kind != SPECPDL_BACKTRACE) | ||
| 225 | pdl--; | ||
| 226 | return pdl; | ||
| 227 | } | ||
| 228 | |||
| 216 | union specbinding * | 229 | union specbinding * |
| 217 | backtrace_next (union specbinding *pdl) | 230 | backtrace_next (union specbinding *pdl) |
| 218 | { | 231 | { |
| @@ -222,6 +235,15 @@ backtrace_next (union specbinding *pdl) | |||
| 222 | return pdl; | 235 | return pdl; |
| 223 | } | 236 | } |
| 224 | 237 | ||
| 238 | static union specbinding * | ||
| 239 | backtrace_thread_next (struct thread_state *tstate, union specbinding *pdl) | ||
| 240 | { | ||
| 241 | pdl--; | ||
| 242 | while (backtrace_thread_p (tstate, pdl) && pdl->kind != SPECPDL_BACKTRACE) | ||
| 243 | pdl--; | ||
| 244 | return pdl; | ||
| 245 | } | ||
| 246 | |||
| 225 | void | 247 | void |
| 226 | init_eval_once (void) | 248 | init_eval_once (void) |
| 227 | { | 249 | { |
| @@ -3730,6 +3752,42 @@ Return the result of FUNCTION, or nil if no matching frame could be found. */) | |||
| 3730 | return backtrace_frame_apply (function, get_backtrace_frame (nframes, base)); | 3752 | return backtrace_frame_apply (function, get_backtrace_frame (nframes, base)); |
| 3731 | } | 3753 | } |
| 3732 | 3754 | ||
| 3755 | DEFUN ("backtrace--frames-from-thread", Fbacktrace_frames_from_thread, | ||
| 3756 | Sbacktrace_frames_from_thread, 1, 1, NULL, | ||
| 3757 | doc: /* Return the list of backtrace frames from current execution point in THREAD. | ||
| 3758 | If a frame has not evaluated the arguments yet (or is a special form), | ||
| 3759 | the value of the list element is (nil FUNCTION ARG-FORMS...). | ||
| 3760 | If a frame has evaluated its arguments and called its function already, | ||
| 3761 | the value of the list element is (t FUNCTION ARG-VALUES...). | ||
| 3762 | A &rest arg is represented as the tail of the list ARG-VALUES. | ||
| 3763 | FUNCTION is whatever was supplied as car of evaluated list, | ||
| 3764 | or a lambda expression for macro calls. */) | ||
| 3765 | (Lisp_Object thread) | ||
| 3766 | { | ||
| 3767 | struct thread_state *tstate; | ||
| 3768 | CHECK_THREAD (thread); | ||
| 3769 | tstate = XTHREAD (thread); | ||
| 3770 | |||
| 3771 | union specbinding *pdl = backtrace_thread_top (tstate); | ||
| 3772 | Lisp_Object list = Qnil; | ||
| 3773 | |||
| 3774 | while (backtrace_thread_p (tstate, pdl)) | ||
| 3775 | { | ||
| 3776 | Lisp_Object frame; | ||
| 3777 | if (backtrace_nargs (pdl) == UNEVALLED) | ||
| 3778 | frame = Fcons (Qnil, | ||
| 3779 | Fcons (backtrace_function (pdl), *backtrace_args (pdl))); | ||
| 3780 | else | ||
| 3781 | { | ||
| 3782 | Lisp_Object tem = Flist (backtrace_nargs (pdl), backtrace_args (pdl)); | ||
| 3783 | frame = Fcons (Qt, Fcons (backtrace_function (pdl), tem)); | ||
| 3784 | } | ||
| 3785 | list = Fcons (frame, list); | ||
| 3786 | pdl = backtrace_thread_next (tstate, pdl); | ||
| 3787 | } | ||
| 3788 | return Fnreverse (list); | ||
| 3789 | } | ||
| 3790 | |||
| 3733 | /* For backtrace-eval, we want to temporarily unwind the last few elements of | 3791 | /* For backtrace-eval, we want to temporarily unwind the last few elements of |
| 3734 | the specpdl stack, and then rewind them. We store the pre-unwind values | 3792 | the specpdl stack, and then rewind them. We store the pre-unwind values |
| 3735 | directly in the pre-existing specpdl elements (i.e. we swap the current | 3793 | directly in the pre-existing specpdl elements (i.e. we swap the current |
| @@ -4205,6 +4263,7 @@ alist of active lexical bindings. */); | |||
| 4205 | DEFSYM (QCdebug_on_exit, ":debug-on-exit"); | 4263 | DEFSYM (QCdebug_on_exit, ":debug-on-exit"); |
| 4206 | defsubr (&Smapbacktrace); | 4264 | defsubr (&Smapbacktrace); |
| 4207 | defsubr (&Sbacktrace_frame_internal); | 4265 | defsubr (&Sbacktrace_frame_internal); |
| 4266 | defsubr (&Sbacktrace_frames_from_thread); | ||
| 4208 | defsubr (&Sbacktrace_eval); | 4267 | defsubr (&Sbacktrace_eval); |
| 4209 | defsubr (&Sbacktrace__locals); | 4268 | defsubr (&Sbacktrace__locals); |
| 4210 | defsubr (&Sspecial_variable_p); | 4269 | defsubr (&Sspecial_variable_p); |