aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGemini Lasswell2018-08-09 14:21:57 -0700
committerGemini Lasswell2018-09-09 07:41:49 -0700
commit3fb8f306475a87a30a7dd68387d8da859cffc90a (patch)
tree8d8f600a2bae48e351a7424648ef100d402ae261 /src
parentdc5c76c37488d6fd546eefb33cea1edf4d13859e (diff)
downloademacs-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.c59
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
204backtrace_p (union specbinding *pdl) 204backtrace_p (union specbinding *pdl)
205{ return pdl >= specpdl; } 205{ return pdl >= specpdl; }
206 206
207static bool
208backtrace_thread_p (struct thread_state *tstate, union specbinding *pdl)
209{ return pdl >= tstate->m_specpdl; }
210
207union specbinding * 211union specbinding *
208backtrace_top (void) 212backtrace_top (void)
209{ 213{
@@ -213,6 +217,15 @@ backtrace_top (void)
213 return pdl; 217 return pdl;
214} 218}
215 219
220static union specbinding *
221backtrace_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
216union specbinding * 229union specbinding *
217backtrace_next (union specbinding *pdl) 230backtrace_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
238static union specbinding *
239backtrace_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
225void 247void
226init_eval_once (void) 248init_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
3755DEFUN ("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.
3758If a frame has not evaluated the arguments yet (or is a special form),
3759the value of the list element is (nil FUNCTION ARG-FORMS...).
3760If a frame has evaluated its arguments and called its function already,
3761the value of the list element is (t FUNCTION ARG-VALUES...).
3762A &rest arg is represented as the tail of the list ARG-VALUES.
3763FUNCTION is whatever was supplied as car of evaluated list,
3764or 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);