summaryrefslogtreecommitdiff
path: root/.emacs.d/init.el
diff options
context:
space:
mode:
Diffstat (limited to '.emacs.d/init.el')
-rw-r--r--.emacs.d/init.el94
1 files changed, 63 insertions, 31 deletions
diff --git a/.emacs.d/init.el b/.emacs.d/init.el
index e66dd3ad..2b955f63 100644
--- a/.emacs.d/init.el
+++ b/.emacs.d/init.el
@@ -2274,40 +2274,72 @@ Called by '~/src/dotfiles/bin/emacsclient --spw/update-environment'."
(let ((slime-dispatching-connection connection))
(slime-eval cl-form))))))
-(defvar-local spw/gdbmacs-target-emacs nil)
-
-(defun spw/gdbmacs-attach (pid)
- (interactive "nEmacs PID: ")
- (when-let ((proc (and (boundp 'gud-comint-buffer)
- (get-buffer-process gud-comint-buffer))))
- (if (string= gdb-inferior-status "signal-received")
- ;; Avoid wiping out useful info.
- (error "Possibly Emacs just crashed; not attaching for now")
- (set-process-query-on-exit-flag proc nil)
- (kill-buffer gud-comint-buffer)))
- (require 'gdb-mi)
- (let ((default-directory (expand-file-name "~/src/emacs/")))
- (gdb-reset)
- (gdb (format "gdb -i=mi --pid=%d src/emacs" pid))
- (setq spw/gdbmacs-target-emacs pid)
- (gud-basic-call "continue")))
-
-(defun spw/remote-gdbmacs-attach ()
- (interactive)
- (call-process "emacsclient" nil "*gdbmacs-emacsclient*" nil
- "--socket-name=gdbmacs" "--spw/installed"
- "-e" (prin1-to-string `(spw/gdbmacs-attach ,(emacs-pid)))))
-
-(defun spw/maybe-remote-gdbmacs-attach ()
- (when (and (eq (daemonp) t)
- (file-in-directory-p invocation-directory "~/src/emacs/"))
- (spw/remote-gdbmacs-attach)))
-(add-hook 'after-init-hook #'spw/maybe-remote-gdbmacs-attach)
+(defun spw/daemon-pid (&optional name)
+ ;; We don't use `server-eval-at' because perhaps we are trying to attach gdb
+ ;; to a wedged Emacs.
+ (let ((socket (file-name-concat server-socket-dir (or name "server"))))
+ (and (file-exists-p socket)
+ (and-let* ((output (car (process-lines "ss" "-Hplx" "src" socket))))
+ (and (string-match "pid=\\([[:digit:]]+\\)" output)
+ (string-to-number (match-string 1 output)))))))
+
+(defvar-local spw/gdbmacs-target-pid nil)
+(defvar-local spw/gdbmacs-target-name nil)
+
+(defun spw/gdbmacs-attach (&optional name)
+ (let (pid
+ (arg (if name (concat "--fg-daemon=" name) "--fg-daemon"))
+ (proc (and (boundp 'gud-comint-buffer)
+ (get-buffer-process gud-comint-buffer))))
+ (when (and proc (string= gdb-inferior-status "signal-received"))
+ ;; Avoid wiping out useful info.
+ (error "Possibly Emacs just crashed; not attaching for now"))
+ (require 'gdb-mi)
+ (cl-flet ((run-or-continue ()
+ (gdb-wait-for-pending
+ (lambda ()
+ (with-current-buffer gud-comint-buffer
+ (setq spw/gdbmacs-target-pid pid
+ spw/gdbmacs-target-name name))
+ (if pid
+ (gud-basic-call "continue")
+ (gud-basic-call "set cwd ~")
+ (gdb-wait-for-pending
+ (lambda () (gud-basic-call "run"))))))))
+ (gdb-wait-for-pending
+ (if (and proc
+ ;; Check it looks safe to re-use existing gdb process.
+ (string-prefix-p "exited" gdb-inferior-status)
+ (file-in-directory-p
+ (buffer-local-value 'default-directory gud-comint-buffer)
+ (expand-file-name "~/src/emacs/")))
+ (lambda ()
+ (gud-basic-call (if (setq pid (spw/daemon-pid name))
+ (format "attach %d" pid)
+ (format "set args %s" arg)))
+ (run-or-continue))
+ ;; Start up a new process.
+ (lambda ()
+ (when (buffer-live-p gud-comint-buffer)
+ (when proc (set-process-query-on-exit-flag proc nil))
+ (kill-buffer gud-comint-buffer))
+ (gdb-wait-for-pending
+ (lambda ()
+ (let ((default-directory (expand-file-name "~/src/emacs/")))
+ (gdb (if (setq pid (spw/daemon-pid name))
+ (format "gdb -i=mi --pid=%d src/emacs" pid)
+ (format "gdb -i=mi --args src/emacs %s" arg))))
+ (run-or-continue)))))))))
;; C-c C-z to attempt to return control to the debugger.
+;;
+;; In the --fg-daemon case, AIUI we are here working around this:
+;; <https://lwn.net/Articles/909496/>.
(defun spw/comint-stop-subjob (orig-fun)
- (if spw/gdbmacs-target-emacs
- (signal-process spw/gdbmacs-target-emacs 'SIGTSTP)
+ (if-let ((pid (or spw/gdbmacs-target-pid
+ (setq spw/gdbmacs-target-pid
+ (spw/daemon-pid spw/gdbmacs-target-name)))))
+ (signal-process pid 'SIGTSTP)
(funcall orig-fun)))
(advice-add 'comint-stop-subjob :around #'spw/comint-stop-subjob)