From a7b8b3844b1b928664417240f366abd9c559b701 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sat, 14 Jan 2023 11:14:23 -0700 Subject: emacsclient wrapper: C-i E handles case where primary daemon wedged --- bin/emacsclient | 94 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 42 deletions(-) (limited to 'bin/emacsclient') diff --git a/bin/emacsclient b/bin/emacsclient index fe9335a5..a6c6cb14 100755 --- a/bin/emacsclient +++ b/bin/emacsclient @@ -81,8 +81,8 @@ eval set -- "$getopt" get_listener () { local socket="$1" - local listener=$(ss -Hplx src "$socket" \ - | perl -wne'/pid=(\d+)/ and print $1') + local listener=$(ss -plx src "$socket" \ + | perl -wne'$tmp = $_; END { $tmp =~ /pid=(\d+)/ and print $1 }') if [ -z "$listener" -a -e "$socket" ]; then # Nothing is listening: remove dangling socket. rm "$socket" @@ -91,6 +91,15 @@ get_listener () { fi } +gud_status () { + gud_status="$(exec -a emacsclient "$installed_emacsclient" -sgdbmacs -w2 \ + --eval '(and (boundp '"'"'gud-comint-buffer) + (get-buffer-process gud-comint-buffer) + (string= "signal-received" + gdb-inferior-status))')" + return $? +} + maybe_notify () { echo >&2 "$1" $was_set && ! [ -t 2 ] \ @@ -189,25 +198,33 @@ fi # Make it possible, with primary session, to quickly replace in-tree Emacs # with installed Emacs. See 'C-i E' Sway/i3 binding. if [ -z "$daemon_name" ] && $devel_running && $want_installed; then - inotifywait -qq --timeout "${timeout:-15}" -e delete_self "$socket" & - inotifywait=$! - kill "$listener" - - # Detach gdb so that Emacs can handle the SIGTERM. We also have to quit - # gdb so that `spw/gdbmacs-attach' doesn't look at `gdb-inferior-status'. - if [ -n "${gdbmacs:=$(get_listener ${socket_dir}gdbmacs)}" ]; then \ - ( exec -a emacsclient "$installed_emacsclient" -sgdbmacs -w2 \ - --eval '(gdb-wait-for-pending - (lambda () - (gud-basic-call "detach") - (gdb-wait-for-pending - (lambda () - (gud-basic-call "quit")))))' ) \ - || fail "gdbmacs detach request failed" - fi + # If in-tree Emacs appears wedged, just delete the socket and start up an + # installed daemon. The idea is that I'll only type C-i E if I know + # that's not just wedged but crashed, and I want to keep that state in gdb + # but get another primary daemon up in the meantime. + if gud_status && [ "$gud_status" = t ]; then + rm "$socket" + else + inotifywait -qq --timeout "${timeout:-15}" -e delete_self "$socket" & + inotifywait=$! + kill "$listener" + + # Detach gdb so that Emacs can handle the SIGTERM. We also have to + # quit gdb so that `spw/gdbmacs-attach' ignores `gdb-inferior-status'. + if [ -n "${gdbmacs:=$(get_listener ${socket_dir}gdbmacs)}" ]; then \ + ( exec -a emacsclient "$installed_emacsclient" -sgdbmacs -w2 \ + --eval '(gdb-wait-for-pending + (lambda () + (gud-basic-call "detach") + (gdb-wait-for-pending + (lambda () + (gud-basic-call "quit")))))' ) \ + || fail "gdbmacs detach request failed" + fi - wait_inotifywait \ - || fail "inotifywait(1) timed out waiting for socket deletion" + wait_inotifywait \ + || fail "inotifywait(1) timed out waiting for socket deletion" + fi listener= devel_running=false fi @@ -230,28 +247,21 @@ if ! $want_installed && ! $installed_running && [ -x "$devel_emacsclient" ] \ emacsclient=("$devel_emacsclient") if [ -z "$daemon_name" ] && ! $want_version; then spw_flock 4 gdbmacs - if [ -n "${gdbmacs:=$(get_listener ${socket_dir}gdbmacs)}" ]; then - # If the primary session is known to be stopped, ask gdbmacs to - # handle the request: it's probably C-i e or editing via EDITOR. - # - # Ignore a failure to obtain any information here, because one - # likely cause is that the request times out because gdbmacs is - # busy starting up Gnus. In that case we'd rather just try - # sending the request to the primary session anyway. - # - # Ideally we could know that emacsclient exited non-zero only - # because of a timeout, but currently that can be done only by - # parsing emacsclient's output: see Emacs bug#60592. - gud_status="$(exec -a emacsclient "$installed_emacsclient" \ - -sgdbmacs -w2 --eval \ - '(and (boundp '"'"'gud-comint-buffer) - (get-buffer-process gud-comint-buffer) - (string= "signal-received" - gdb-inferior-status))')" - if [ $? -eq 0 -a "$gud_status" = t ]; then - maybe_notify "in-tree Emacs appears to be wedged" - pass_to_gdbmacs "$@" - fi + # If the primary session is known to be stopped, ask gdbmacs to + # handle the request: it's probably C-i e or editing via EDITOR. + # + # Ignore a failure to obtain any information here, because one + # likely cause is that the request times out because gdbmacs is + # busy starting up Gnus. In that case we'd rather just try + # sending the request to the primary session anyway. + # + # Ideally we could know that emacsclient exited non-zero only + # because of a timeout, but currently that can be done only by + # parsing emacsclient's output: see Emacs bug#60592. + if [ -n "${gdbmacs:=$(get_listener ${socket_dir}gdbmacs)}" ] \ + && gud_status && [ "$gud_status" = t ]; then + maybe_notify "in-tree Emacs appears to be wedged" + pass_to_gdbmacs "$@" fi fi else -- cgit v1.2.3