vpn eww and eww crash
This commit is contained in:
@@ -34,3 +34,10 @@
|
||||
.bt-device-btn:hover { @include background-active; }
|
||||
.net-toggle-on, .bt-btn-on { @include color-base; }
|
||||
.net-toggle-off, .bt-btn-off { @include color-inactive; }
|
||||
|
||||
// WireGuard
|
||||
.wg-accent { background-color: $base0E; }
|
||||
.wg-row { margin-bottom: $popup-scale * 4pt; }
|
||||
.wg-name { font-size: 0.78em; font-weight: bold; }
|
||||
.wg-up { @include color-base; }
|
||||
.wg-down { @include color-inactive; }
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
(defwidget clock-mod []
|
||||
(module
|
||||
(eventbox
|
||||
:onhover "${EWW_CMD} update date_rev=true"
|
||||
:onhoverlost "${EWW_CMD} update date_rev=false"
|
||||
:onhover "${EWW_CMD} --no-daemonize update date_rev=true"
|
||||
:onhoverlost "${EWW_CMD} --no-daemonize update date_rev=false"
|
||||
:onclick "scripts/panel-toggle clock"
|
||||
:onrightclick "scripts/powermenu-toggle"
|
||||
(box
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(deflisten net
|
||||
:initial '{"wifi":{"connected":false,"enabled":false,"icon":"","ssid":"","ip":"","freq":0,"band":"","gen":"","signal":0},"ethernet":{"connected":false,"interface":"","ip":"","speed":""},"usb":{"connected":false,"interface":"","ip":""}}'
|
||||
:initial '{"wifi":{"connected":false,"enabled":false,"icon":"","ssid":"","ip":"","freq":0,"band":"","gen":"","signal":0},"ethernet":{"connected":false,"interface":"","ip":"","speed":""},"usb":{"connected":false,"interface":"","ip":""},"wireguard":[],"vpn":{"up":false,"name":""}}'
|
||||
"scripts/net/net")
|
||||
|
||||
(deflisten bt
|
||||
@@ -20,6 +20,11 @@
|
||||
:class "net-icon net-active"
|
||||
:tooltip "USB: Connected"
|
||||
:text "")
|
||||
(label
|
||||
:visible {net.vpn.up}
|
||||
:class "net-icon net-active"
|
||||
:tooltip "VPN: ${net.vpn.name}"
|
||||
:text "")
|
||||
(label
|
||||
:class "net-icon ${net.wifi.connected ? 'net-active' : 'net-dim'}"
|
||||
:tooltip {net.wifi.connected ? "WiFi: ${net.wifi.ssid}" : "WiFi: Disconnected"}
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
# top of every wrapped script, right after setting PATH.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Every eww client call goes through this wrapper. A client waits only 100 ms
|
||||
# for the daemon's reply; a slower command (opening the popup) would otherwise
|
||||
# make a plain `eww open` fork a second daemon that takes over the socket —
|
||||
# the "two bars" bug. With --no-daemonize it is just an error, and the daemon
|
||||
# still carries out the command.
|
||||
eww() { command eww --no-daemonize "$@"; }
|
||||
|
||||
# Print the payload only when it differs from the previous one.
|
||||
emit() {
|
||||
[[ $1 == "${EMIT_LAST-}" ]] && return 0
|
||||
|
||||
@@ -70,8 +70,60 @@ state() {
|
||||
"$w_connected" "$w_enabled" "$w_icon" "$(jstr "$w_ssid")" "$w_ip" "${w_freq:-0}" "$(band "$w_freq")" "$w_gen" "${w_signal:-0}"
|
||||
printf '"ethernet":{"connected":%s,"interface":"%s","ip":"%s","speed":"%s"},' \
|
||||
"$e_connected" "$eth" "$e_ip" "$e_speed"
|
||||
printf '"usb":{"connected":%s,"interface":"%s","ip":"%s"}}' \
|
||||
printf '"usb":{"connected":%s,"interface":"%s","ip":"%s"},' \
|
||||
"$u_connected" "$usb" "$u_ip"
|
||||
wg_json
|
||||
printf '}'
|
||||
}
|
||||
|
||||
# --- WireGuard: interfaces from the wireguard-<name>.service units (so a
|
||||
# tunnel that is down still shows up) plus any live wireguard-type link.
|
||||
# `wg show` needs root, so peer names and the endpoint come from the peer
|
||||
# units instead.
|
||||
|
||||
wg_ifaces() {
|
||||
{
|
||||
systemctl list-units --all --plain --no-legend 'wireguard-*.service' 2>/dev/null \
|
||||
| awk '$1 !~ /-peer-/ { sub(/^wireguard-/, "", $1); sub(/\.service$/, "", $1); print $1 }'
|
||||
ip -d -o link 2>/dev/null | awk '/ wireguard / { sub(":", "", $2); print $2 }'
|
||||
} | sort -u
|
||||
}
|
||||
|
||||
human_bytes() {
|
||||
awk -v b="${1:-0}" 'BEGIN {
|
||||
split("B KiB MiB GiB TiB", u, " "); i = 1
|
||||
while (b >= 1024 && i < 5) { b /= 1024; i++ }
|
||||
printf (i == 1 ? "%d %s" : "%.1f %s"), b, u[i] }'
|
||||
}
|
||||
|
||||
wg_json() { # prints the "wireguard" array and the "vpn" summary
|
||||
local name up ip rx tx peers endpoint peer_unit peer_script sep="" out="[" vpn_up=false vpn_name=""
|
||||
while read -r name; do
|
||||
[[ -n $name ]] || continue
|
||||
up=false ip="" rx=0 tx=0 endpoint=""
|
||||
if [[ -d /sys/class/net/$name ]]; then
|
||||
ip -o link show "$name" 2>/dev/null | grep -q '<[^>]*UP' && up=true
|
||||
ip=$(ipv4 "$name")
|
||||
rx=$(<"/sys/class/net/$name/statistics/rx_bytes")
|
||||
tx=$(<"/sys/class/net/$name/statistics/tx_bytes")
|
||||
fi
|
||||
peers=$(systemctl list-units --all --plain --no-legend "wireguard-$name-peer-*.service" 2>/dev/null \
|
||||
| awk '{ print $1 }' | sed "s/^wireguard-$name-peer-//; s/\.service\$//" | paste -sd, -)
|
||||
peer_unit=$(systemctl list-units --all --plain --no-legend "wireguard-$name-peer-*.service" 2>/dev/null \
|
||||
| awk 'NR == 1 { print $1 }')
|
||||
# NixOS puts `wg set … endpoint "host:port"` in the peer unit's start script
|
||||
if [[ -n $peer_unit ]]; then
|
||||
peer_script=$(systemctl show -p ExecStart --value "$peer_unit" 2>/dev/null \
|
||||
| sed -n 's/.*path=\([^ ;]*\).*/\1/p' | awk 'NR == 1')
|
||||
[[ -r $peer_script ]] && endpoint=$(grep -o 'endpoint "[^"]*"' "$peer_script" 2>/dev/null \
|
||||
| awk -F'"' 'NR == 1 { print $2 }')
|
||||
fi
|
||||
if [[ $up == true && $vpn_up == false ]]; then vpn_up=true vpn_name=$name; fi
|
||||
[[ -z $vpn_name ]] && vpn_name=$name
|
||||
out+="$sep{\"name\":\"$(jstr "$name")\",\"up\":$up,\"ip\":\"$ip\",\"rx\":\"$(human_bytes "$rx")\",\"tx\":\"$(human_bytes "$tx")\",\"peers\":\"$(jstr "$peers")\",\"endpoint\":\"$(jstr "$endpoint")\"}"
|
||||
sep=,
|
||||
done < <(wg_ifaces)
|
||||
printf '"wireguard":%s],"vpn":{"up":%s,"name":"%s"}' "$out" "$vpn_up" "$(jstr "$vpn_name")"
|
||||
}
|
||||
|
||||
refresh() { emit "$(state)"; }
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bring the WireGuard tunnel $1 down (stop its service, which takes the peer
|
||||
# units with it) or up (start its target, which pulls service and peers).
|
||||
# Needs the polkit rule from modules/nixos/system/network/wireguard.
|
||||
name=$1
|
||||
[[ -n $name ]] || exit 64
|
||||
if [[ -d /sys/class/net/$name ]]; then
|
||||
systemctl stop "wireguard-$name.service"
|
||||
else
|
||||
systemctl start "wireguard-$name.target"
|
||||
fi
|
||||
@@ -4,6 +4,11 @@
|
||||
# The popup hosts every panel behind revealers, so switching panels while it
|
||||
# is open is just a variable update (animated, no scripts restarted). It is
|
||||
# only closed and re-opened when it has to move to another monitor.
|
||||
#
|
||||
# `eww open popup` takes longer than the client's 100 ms reply deadline, so
|
||||
# its exit status and error output are meaningless and ignored (the daemon
|
||||
# carries the command out anyway; the lib's eww wrapper makes sure a slow
|
||||
# reply can never spawn a second daemon).
|
||||
panel=$1
|
||||
[[ -n $panel ]] || exit 64
|
||||
|
||||
@@ -12,7 +17,7 @@ panel=$1
|
||||
exec 9>"${XDG_RUNTIME_DIR:-/tmp}/eww-panel-toggle.lock"
|
||||
flock -n 9 || exit 0
|
||||
|
||||
ew() { timeout 5 eww "$@" 9>&-; }
|
||||
ew() { eww "$@" 9>&-; }
|
||||
|
||||
current=$(ew get active-panel 2>/dev/null | tr -d '"')
|
||||
popup_screen=$(ew get popup-screen 2>/dev/null | tr -d '"')
|
||||
@@ -21,15 +26,16 @@ if ew active-windows 2>/dev/null | grep -qx 'popup: popup'; then open=1; else op
|
||||
|
||||
if ((open)) && [[ $current == "$panel" ]]; then
|
||||
ew update active-panel=
|
||||
ew close popup
|
||||
ew close popup 2>/dev/null
|
||||
elif ((open)) && [[ -n $screen && $popup_screen == "$screen" ]]; then
|
||||
ew update active-panel="$panel"
|
||||
else
|
||||
((open)) && ew close popup
|
||||
((open)) && ew close popup 2>/dev/null
|
||||
ew update active-panel="$panel" popup-screen="$screen"
|
||||
if [[ -n $screen ]]; then
|
||||
ew open popup --screen "$screen"
|
||||
ew open popup --screen "$screen" >/dev/null 2>&1
|
||||
else
|
||||
ew open popup
|
||||
ew open popup >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
# Toggle the full-screen power menu on the focused monitor.
|
||||
ew() { timeout 5 eww "$@"; }
|
||||
ew close popup 2>/dev/null
|
||||
ew update active-panel=
|
||||
# Toggle the full-screen power menu on the focused monitor. The open's exit
|
||||
# status is ignored: it exceeds the client's 100 ms reply deadline.
|
||||
eww close popup 2>/dev/null
|
||||
eww update active-panel= 2>/dev/null
|
||||
screen=$(eww-bar focused)
|
||||
if [[ -n $screen ]]; then
|
||||
ew open powermenu --toggle --screen "$screen"
|
||||
eww open powermenu --toggle --screen "$screen" >/dev/null 2>&1
|
||||
else
|
||||
ew open powermenu --toggle
|
||||
eww open powermenu --toggle >/dev/null 2>&1
|
||||
fi
|
||||
exit 0
|
||||
|
||||
@@ -83,6 +83,29 @@
|
||||
:visible {!bt.powered}
|
||||
:text "Disabled")))
|
||||
|
||||
; --- WireGuard ---
|
||||
|
||||
(defwidget wg-row [wg]
|
||||
(box :orientation "v" :space-evenly false :class "wg-row"
|
||||
(box :orientation "h" :space-evenly false :valign "center"
|
||||
(label :class "wg-name ${wg.up ? 'wg-up' : 'wg-down'}" :halign "start" :hexpand true :text {wg.name})
|
||||
(button
|
||||
:class "net-toggle-btn ${wg.up ? 'net-toggle-on' : 'net-toggle-off'}"
|
||||
:onclick "scripts/net/wg-toggle ${wg.name}"
|
||||
:tooltip {wg.up ? "Disconnect" : "Connect"}
|
||||
(label :text {wg.up ? "" : ""})))
|
||||
(box :orientation "v" :space-evenly false :visible {wg.up}
|
||||
(netinfo-row :label "IP" :value {wg.ip})
|
||||
(netinfo-row :label "Peer" :value {wg.endpoint != "" ? "${wg.peers} · ${wg.endpoint}" : wg.peers})
|
||||
(netinfo-row :label "Traffic" :value " ${wg.rx} ${wg.tx}"))
|
||||
(label :class "netinfo-dim" :halign "start" :visible {!wg.up} :text "Down")))
|
||||
|
||||
(defwidget wireguard-net-section []
|
||||
(box :orientation "v" :space-evenly false :class "sys-section"
|
||||
(section-header :title "WireGuard" :accent "wg-accent")
|
||||
(for wg in {net.wireguard}
|
||||
(wg-row :wg {wg}))))
|
||||
|
||||
; --- Root ---
|
||||
|
||||
(defwidget net-win []
|
||||
@@ -94,4 +117,7 @@
|
||||
(box :class "section-sep")
|
||||
(wifi-net-section)
|
||||
(box :class "section-sep")
|
||||
(box :visible {arraylength(net.wireguard) > 0} :space-evenly false :orientation "v"
|
||||
(wireguard-net-section)
|
||||
(box :class "section-sep"))
|
||||
(bluetooth-net-section)))
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
(pm-btn :icon "" :label "Sign out"
|
||||
:onclick "hyprctl eval \"hl.dispatch(hl.dsp.exit())\"")
|
||||
(pm-btn :icon "" :label "Cancel"
|
||||
:onclick "eww close powermenu")))))))
|
||||
:onclick "${EWW_CMD} --no-daemonize close powermenu")))))))
|
||||
|
||||
(defwindow powermenu
|
||||
:monitor 0
|
||||
|
||||
@@ -20,6 +20,7 @@ let
|
||||
"scripts/net/net" = mkScript "net" ./bar/scripts/net/net [ iproute2 wpa_supplicant ];
|
||||
"scripts/net/bt" = mkScript "bt" ./bar/scripts/net/bt [ jq glib ];
|
||||
"scripts/net/bt-toggle" = mkScript "bt-toggle" ./bar/scripts/net/bt-toggle [ bluez ];
|
||||
"scripts/net/wg-toggle" = mkScript "wg-toggle" ./bar/scripts/net/wg-toggle [ ];
|
||||
"scripts/sys/gpu" = mkScript "gpu" ./bar/scripts/sys/gpu [ custom.amdgpu_top jq ];
|
||||
"scripts/sys/memory" = mkScript "memory" ./bar/scripts/sys/memory [ ];
|
||||
"scripts/sys/battery" = mkScript "battery" ./bar/scripts/sys/battery [ ];
|
||||
|
||||
@@ -36,6 +36,20 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# Let the desktop (eww network panel, scripts/net/wg-toggle) bring the
|
||||
# tunnel up and down. eww runs as a user service outside the login
|
||||
# session, where polkit cannot ask for a password, so wheel users may
|
||||
# start/stop wireguard-* units without one.
|
||||
security.polkit.extraConfig = ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (action.id == "org.freedesktop.systemd1.manage-units" &&
|
||||
subject.isInGroup("wheel") &&
|
||||
/^wireguard-/.test(action.lookup("unit") || "")) {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
});
|
||||
'';
|
||||
|
||||
systemd.services."wireguard-wg0-peer-vpn-helcel" = {
|
||||
after = [ "network-online.target" "nss-lookup.target" ];
|
||||
bindsTo = [ "network-online.target" ];
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
, gnugrep
|
||||
, gnused
|
||||
, hyprland
|
||||
, iproute2
|
||||
, jq
|
||||
, procps
|
||||
, systemd
|
||||
@@ -15,6 +16,6 @@
|
||||
# profiles and the user (`eww-bar status`, `eww-bar reset`).
|
||||
writeShellApplication {
|
||||
name = "eww-bar";
|
||||
runtimeInputs = [ coreutils eww gnugrep gnused hyprland jq procps systemd util-linux ];
|
||||
runtimeInputs = [ coreutils eww gnugrep gnused hyprland iproute2 jq procps systemd util-linux ];
|
||||
text = builtins.readFile ./eww-bar.sh;
|
||||
}
|
||||
|
||||
+98
-34
@@ -1,9 +1,17 @@
|
||||
# eww-bar — lifecycle manager for the eww daemon and the bar window.
|
||||
#
|
||||
# The daemon is owned by the user unit eww.service. Every window open goes
|
||||
# through `ensure` first: a plain `eww open` against a dead or stale socket
|
||||
# silently forks a *second* daemon that takes over the socket path and orphans
|
||||
# the first daemon's surfaces ("a bar/popup I can't close").
|
||||
# The daemon is owned by the user unit eww.service. Two eww facts shape this
|
||||
# script:
|
||||
#
|
||||
# * A client waits only 100 ms for the daemon's reply. Any slower command
|
||||
# (opening the popup, reload) fails on the client side, and a plain
|
||||
# `eww open` then forks a SECOND daemon that takes over the socket path and
|
||||
# orphans the first one's surfaces ("two bars", "a popup I can't close").
|
||||
# Every client call here passes --no-daemonize, which turns that into a
|
||||
# harmless error; outcomes are verified with `active-windows`, never with
|
||||
# the exit status.
|
||||
# * `eww ping` is answered by the IPC thread; `eww active-windows` by the GTK
|
||||
# main loop. Only the latter proves the UI is alive.
|
||||
#
|
||||
# SCREEN is a GDK monitor index (0), a connector name (DP-1) or
|
||||
# desc:<prefix of the description shown by `hyprctl monitors`>. Descriptions
|
||||
@@ -23,7 +31,7 @@ usage: eww-bar COMMAND [ARGS]
|
||||
check health check run by eww-watchdog.timer
|
||||
clean ExecStartPre: kill stray daemons, wipe stale sockets
|
||||
focused print the name of the focused Hyprland monitor
|
||||
status show unit state, open windows and the bar's screen
|
||||
status show unit state, socket owner, open windows and screen
|
||||
USAGE
|
||||
}
|
||||
|
||||
@@ -42,6 +50,25 @@ mkdir -p "$state_dir"
|
||||
|
||||
log() { printf 'eww-bar: %s\n' "$*" >&2; }
|
||||
|
||||
# ---------------------------------------------------------------- client ---
|
||||
|
||||
# fd 9 (the lock) is closed for every client call so nothing can inherit it.
|
||||
ewwc() { timeout 5 eww --no-daemonize "$@" 9>&-; }
|
||||
|
||||
ping_daemon() { ewwc ping >/dev/null 2>&1; }
|
||||
list_windows() { ewwc active-windows 2>/dev/null || true; }
|
||||
bar_open() { list_windows | grep -qx 'bar: bar'; }
|
||||
|
||||
# wait_for_window NAME [SECONDS]
|
||||
wait_for_window() {
|
||||
local i n=$((${2:-5} * 5))
|
||||
for ((i = 0; i < n; i++)); do
|
||||
list_windows | grep -qx "$1: $1" && return 0
|
||||
sleep 0.2
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------- daemon ---
|
||||
|
||||
# nixpkgs wraps eww (wrapGAppsHook), so the running process is `.eww-wrapped`;
|
||||
@@ -60,18 +87,33 @@ unit_running() {
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
main_pid() { systemctl --user show -p MainPID --value "$unit" 2>/dev/null || echo 0; }
|
||||
|
||||
# `eww ping` is answered by the IPC thread and only proves the socket is alive.
|
||||
ping_daemon() { timeout 3 eww ping >/dev/null 2>&1 9>&-; }
|
||||
# pids listening on an eww socket path. After a rival rebinds the path, ss
|
||||
# lists BOTH sockets under the same name (the old one is merely unlinked), so
|
||||
# every pid matters, not just the first.
|
||||
socket_owners() {
|
||||
ss -xlp 2>/dev/null | grep -F "$runtime_dir/eww-server_" \
|
||||
| sed -n 's/.*pid=\([0-9]*\).*/\1/p' | sort -u | tr '\n' ' '
|
||||
}
|
||||
|
||||
# `active-windows` is answered from the GTK main loop, so it also detects a
|
||||
# frozen UI: the reply is then empty instead of listing the windows.
|
||||
# fd 9 is closed for every client call so a daemonizing client (which can
|
||||
# only happen when the socket is dead) can never inherit our lock.
|
||||
list_windows() { timeout 5 eww active-windows 2>/dev/null 9>&- || true; }
|
||||
bar_open() { list_windows | grep -qx 'bar: bar'; }
|
||||
# The socket file is gone while the daemon lives on: a rival that crashed at
|
||||
# startup unlinked it, and no client can reach the daemon any more.
|
||||
socket_missing() { ! ls "$runtime_dir"/eww-server_* >/dev/null 2>&1; }
|
||||
daemon_age() { ps -o etimes= -p "$(main_pid)" 2>/dev/null | tr -d " " || echo 0; }
|
||||
|
||||
healthy() { unit_running && ping_daemon; }
|
||||
# pids of daemons other than the service's main process listening on the socket
|
||||
rival_pids() {
|
||||
local main pid
|
||||
main=$(main_pid)
|
||||
for pid in $(socket_owners); do
|
||||
[[ $pid != "$main" ]] && printf '%s ' "$pid"
|
||||
done
|
||||
return 0
|
||||
}
|
||||
rival_daemon() { [[ -n $(rival_pids) ]]; }
|
||||
|
||||
healthy() { unit_running && ping_daemon && ! rival_daemon; }
|
||||
|
||||
wait_for_daemon() {
|
||||
local i
|
||||
@@ -98,10 +140,13 @@ ensure() {
|
||||
(
|
||||
flock -x 9
|
||||
healthy && exit 0
|
||||
# The unit is (re)starting — possibly running us from ExecStartPost —
|
||||
# so give the daemon time to bind before declaring it dead.
|
||||
if unit_running && wait_for_daemon; then exit 0; fi
|
||||
log "daemon unreachable, restarting $unit"
|
||||
if rival_daemon; then
|
||||
log "a second eww daemon (pid $(rival_pids)) owns the socket"
|
||||
elif unit_running && wait_for_daemon && ! rival_daemon; then
|
||||
# The unit was (re)starting — possibly running us from ExecStartPost.
|
||||
exit 0
|
||||
fi
|
||||
log "daemon unhealthy, restarting $unit"
|
||||
systemctl --user stop "$unit" >/dev/null 2>&1 || true
|
||||
kill_stray_daemons
|
||||
start_unit
|
||||
@@ -142,9 +187,9 @@ current_screen() { cat "$current_file" 2>/dev/null || true; }
|
||||
close_popups() {
|
||||
local w
|
||||
for w in popup powermenu; do
|
||||
timeout 3 eww close "$w" >/dev/null 2>&1 9>&- || true
|
||||
list_windows | grep -qx "$w: $w" && { ewwc close "$w" >/dev/null 2>&1 || true; }
|
||||
done
|
||||
timeout 3 eww update active-panel= >/dev/null 2>&1 9>&- || true
|
||||
ewwc update active-panel= >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
# open_bar [--force] [SPEC]
|
||||
@@ -161,17 +206,21 @@ open_bar() {
|
||||
exit 0
|
||||
fi
|
||||
# Popups may sit on an output that just vanished; `eww open` itself
|
||||
# replaces an already-open bar.
|
||||
# replaces an already-open bar. The exit status is meaningless (100 ms
|
||||
# client deadline), so the result is verified instead.
|
||||
close_popups
|
||||
if ! timeout 10 eww open bar --screen "$screen" >/dev/null 9>&-; then
|
||||
if [[ $screen == "$default_screen" ]]; then
|
||||
log "eww open failed, restarting $unit"
|
||||
ewwc open bar --screen "$screen" >/dev/null 2>&1 || true
|
||||
if ! wait_for_window bar 5; then
|
||||
if [[ $screen != "$default_screen" ]]; then
|
||||
log "cannot open the bar on '$screen', using screen $default_screen"
|
||||
screen=$default_screen
|
||||
ewwc open bar --screen "$screen" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if ! wait_for_window bar 5; then
|
||||
log "the bar does not come up, restarting $unit"
|
||||
restart_unit
|
||||
exit 1
|
||||
fi
|
||||
log "cannot open the bar on '$screen', using screen $default_screen"
|
||||
screen=$default_screen
|
||||
timeout 10 eww open bar --screen "$screen" >/dev/null 9>&- || { restart_unit; exit 1; }
|
||||
fi
|
||||
printf '%s\n' "$spec" >"$screen_file"
|
||||
printf '%s\n' "$screen" >"$current_file"
|
||||
@@ -181,16 +230,20 @@ open_bar() {
|
||||
|
||||
close_bar() {
|
||||
close_popups
|
||||
timeout 3 eww close bar >/dev/null 2>&1 9>&- || true
|
||||
ewwc close bar >/dev/null 2>&1 || true
|
||||
rm -f "$current_file"
|
||||
}
|
||||
|
||||
reload() {
|
||||
ensure || return 1
|
||||
if ! timeout 15 eww reload >/dev/null 9>&-; then
|
||||
log "reload failed, restarting $unit"
|
||||
# Slow: the client always hits its deadline, so ignore the status and
|
||||
# verify that the daemon is still with us afterwards.
|
||||
ewwc reload >/dev/null 2>&1 || true
|
||||
sleep 1
|
||||
if ! wait_for_daemon; then
|
||||
log "daemon lost during reload, restarting $unit"
|
||||
restart_unit
|
||||
return
|
||||
return 0
|
||||
fi
|
||||
open_bar --force
|
||||
}
|
||||
@@ -234,18 +287,28 @@ check() {
|
||||
return 0
|
||||
fi
|
||||
[[ $(unit_state) == active ]] || return 0 # still starting; ExecStartPost handles it
|
||||
if rival_daemon; then
|
||||
log "a second eww daemon (pid $(rival_pids)) owns the socket, restarting $unit"
|
||||
restart_unit
|
||||
return 0
|
||||
fi
|
||||
if socket_missing && (($(daemon_age) > 15)); then
|
||||
log "socket file is gone, restarting $unit"
|
||||
restart_unit
|
||||
return 0
|
||||
fi
|
||||
if ! ping_daemon; then
|
||||
strike "daemon does not answer"
|
||||
return 0
|
||||
fi
|
||||
if bar_open; then
|
||||
if wait_for_window bar 3; then
|
||||
rm -f "$fail_file"
|
||||
return 0
|
||||
fi
|
||||
# Either nothing is open or the main loop is frozen (empty reply). Try to
|
||||
# open the bar: a frozen daemon still won't list it afterwards.
|
||||
open_bar || true
|
||||
if bar_open; then
|
||||
if wait_for_window bar 3; then
|
||||
rm -f "$fail_file"
|
||||
log "bar was missing, reopened"
|
||||
else
|
||||
@@ -255,7 +318,8 @@ check() {
|
||||
|
||||
status() {
|
||||
systemctl --user --no-pager status "$unit" 2>&1 | head -n 12 || true
|
||||
printf '\nwindows:\n'
|
||||
printf '\nsocket listeners: %s(service main pid %s)\n' "$(socket_owners)" "$(main_pid)"
|
||||
printf 'windows:\n'
|
||||
list_windows | sed 's/^/ /'
|
||||
printf 'screen: %s (requested: %s)\n' "$(current_screen)" "$(saved_screen)"
|
||||
printf 'strikes: %s\n' "$(cat "$fail_file" 2>/dev/null || echo 0)"
|
||||
|
||||
Reference in New Issue
Block a user