From 82a13b897f279d9ba5882fb181cc912bbd51b482 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Mon, 24 Oct 2022 13:53:47 -0700 Subject: emacsclient wrapper: add locking around starting up daemons --- bin/emacsclient | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'bin/emacsclient') diff --git a/bin/emacsclient b/bin/emacsclient index 20e243c7..ed1c2215 100755 --- a/bin/emacsclient +++ b/bin/emacsclient @@ -33,7 +33,9 @@ status= daemon_name= gdbmacs= args= -socket_dir="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/emacs/" +xdg="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" +socket_dir="$xdg/emacs/" +locks_dir="$xdg/spw_emacsclient/" get_listener () { local socket="$1" @@ -53,6 +55,15 @@ maybe_notify () { && notify-send --urgency=low --expire-time=10000 "$1" } +spw_flock () { + mkdir -p "$locks_dir" + eval "exec $1<>${locks_dir}$2" + if ! flock --wait 15 "$1"; then + maybe_notify "couldn't lock starting Emacs daemon named $2" + exit 1 + fi +} + die_wedged () { maybe_notify "in-tree Emacs appears to be wedged" # Only exit non-zero if we were expected to start the daemon. @@ -92,6 +103,8 @@ installed_emacsclient=$(PATH=$(echo "$PATH" \ command -v ss >/dev/null || exec "$installed_emacsclient" -a "" "$@" +$want_version || spw_flock 3 "${daemon_name:-server}" + socket="$socket_dir${daemon_name:-server}" listener="$(get_listener $socket)" if [ -n "$listener" ]; then @@ -138,6 +151,7 @@ if ! $want_installed && ! $installed_running \ # ---- Two special cases for primary session that's always under gdb if [ -z "$daemon_name" ] && ! $want_version; then + spw_flock 4 gdbmacs # If devel Emacs is stopped or gdbmacs can't start it, ask gdbmacs to # handle the request: it's probs. C-i e or editing a file via EDITOR. @@ -162,8 +176,9 @@ if ! $want_installed && ! $installed_running \ --exclude "$(egrep_negate ${socket_dir}server)" & inotifywait=$! - if "$installed_emacsclient" -a '' -sgdbmacs \ - --eval '(spw/gdbmacs-attach)'; then + if "$installed_emacsclient" \ + -a '' -sgdbmacs \ + --eval '(spw/gdbmacs-attach)' 3>&- 4>&-; then wait $inotifywait listener=true elif $want_eval || $want_update; then @@ -178,9 +193,11 @@ if ! $want_installed && ! $installed_running \ if $pass_to_gdbmacs; then emacs="$installed_emacs" emacsclient="$installed_emacsclient" + socket="${socket_dir}gdbmacs" listener="$gdbmacs" set -- "$@" -sgdbmacs fi + exec 4>&- fi # ---- End two special cases for primary session that's always under gdb else @@ -210,12 +227,21 @@ if $want_update && [ -n "$listener" ]; then --eval "(spw/update-environment$args))" fi +maybe_hold_lock () { + # Hold on to the lock until daemon has started up. + $want_version || [ -n "$listener" ] \ + || inotifywait -qq -e create "${socket_dir}" \ + --exclude "$(egrep_negate $socket)" & +} + # emacsclient(1) requires an argument. As a special case, if there are no # arguments except -s/--socket-name, and no daemon is running, just start one. # And if there were no arguments but we were requested just to update env # vars, exit peacefully. if [ "$#" -eq "$min_arg" -a -z "$listener" ]; then - exec "$emacs" --daemon"${daemon_name:+=$daemon_name}" + maybe_hold_lock + exec "$emacs" --daemon"${daemon_name:+=$daemon_name}" 3>&- elif ! ( [ "$#" -eq "$min_arg" ] && $want_update ); then - exec "$emacsclient" -a "" "$@" + maybe_hold_lock + exec "$emacsclient" -a "" "$@" 3>&- fi -- cgit v1.2.3