-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix focus reporting leak during pane creation (#2446) #2511
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
082a9d6
2aa1325
58e5b34
90152a1
7a89bec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,141 @@ | ||||||||||||||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||||||||||||||||||||||||||||||||||
| PROJECT_DIR="$(dirname "$SCRIPT_DIR")" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| cd "$PROJECT_DIR" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| hash_stdin() { | ||||||||||||||||||||||||||||||||||
| if command -v shasum >/dev/null 2>&1; then | ||||||||||||||||||||||||||||||||||
| shasum -a 256 | awk '{print $1}' | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| sha256sum | awk '{print $1}' | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| hash_file() { | ||||||||||||||||||||||||||||||||||
| local path="$1" | ||||||||||||||||||||||||||||||||||
| if command -v shasum >/dev/null 2>&1; then | ||||||||||||||||||||||||||||||||||
| shasum -a 256 "$path" | awk '{print $1}' | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| sha256sum "$path" | awk '{print $1}' | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| extract_surface_config_block() { | ||||||||||||||||||||||||||||||||||
| local path="$1" | ||||||||||||||||||||||||||||||||||
| python3 - "$path" <<'PY' | ||||||||||||||||||||||||||||||||||
| from pathlib import Path | ||||||||||||||||||||||||||||||||||
| import sys | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| text = Path(sys.argv[1]).read_text() | ||||||||||||||||||||||||||||||||||
| start = text.index("typedef struct {\n ghostty_platform_e platform_tag;") | ||||||||||||||||||||||||||||||||||
| end = text.index("} ghostty_surface_config_s;") + len("} ghostty_surface_config_s;") | ||||||||||||||||||||||||||||||||||
| print(text[start:end], end="") | ||||||||||||||||||||||||||||||||||
| PY | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
try:
start = text.index("typedef struct {\n ghostty_platform_e platform_tag;")
end = text.index("} ghostty_surface_config_s;") + len("} ghostty_surface_config_s;")
except ValueError as e:
print(f"error: ghostty_surface_config_s block not found in {sys.argv[1]}: {e}", file=sys.stderr)
sys.exit(1) |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if [[ ! -d "$PROJECT_DIR/ghostty" ]]; then | ||||||||||||||||||||||||||||||||||
| echo "error: ghostty submodule is missing. Run ./scripts/setup.sh first." >&2 | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if ! command -v zig >/dev/null 2>&1; then | ||||||||||||||||||||||||||||||||||
| echo "Error: zig is not installed." >&2 | ||||||||||||||||||||||||||||||||||
| echo "Install via: brew install zig" >&2 | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ROOT_SURFACE_CONFIG="$(extract_surface_config_block "$PROJECT_DIR/ghostty.h")" | ||||||||||||||||||||||||||||||||||
| SUBMODULE_SURFACE_CONFIG="$(extract_surface_config_block "$PROJECT_DIR/ghostty/include/ghostty.h")" | ||||||||||||||||||||||||||||||||||
| if [[ "$ROOT_SURFACE_CONFIG" != "$SUBMODULE_SURFACE_CONFIG" ]]; then | ||||||||||||||||||||||||||||||||||
| echo "error: ghostty_surface_config_s is out of sync between ghostty.h and ghostty/include/ghostty.h." >&2 | ||||||||||||||||||||||||||||||||||
| echo "Update the ghostty submodule SHA or sync the checked-in header before building." >&2 | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| GHOSTTY_SHA="$(git -C ghostty rev-parse HEAD)" | ||||||||||||||||||||||||||||||||||
| GHOSTTY_KEY="$GHOSTTY_SHA" | ||||||||||||||||||||||||||||||||||
| UNTRACKED_FILES="$(git -C ghostty ls-files --others --exclude-standard)" | ||||||||||||||||||||||||||||||||||
| if ! git -C ghostty diff --quiet --ignore-submodules=all HEAD -- || [[ -n "$UNTRACKED_FILES" ]]; then | ||||||||||||||||||||||||||||||||||
| DIRTY_HASH="$( | ||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||
| printf 'head=%s\n' "$GHOSTTY_SHA" | ||||||||||||||||||||||||||||||||||
| git -C ghostty diff --binary HEAD -- . | ||||||||||||||||||||||||||||||||||
| if [[ -n "$UNTRACKED_FILES" ]]; then | ||||||||||||||||||||||||||||||||||
| printf '\n--untracked--\n' | ||||||||||||||||||||||||||||||||||
| while IFS= read -r path; do | ||||||||||||||||||||||||||||||||||
| [[ -n "$path" ]] || continue | ||||||||||||||||||||||||||||||||||
| printf 'path=%s\n' "$path" | ||||||||||||||||||||||||||||||||||
| hash_file "$PROJECT_DIR/ghostty/$path" | ||||||||||||||||||||||||||||||||||
| done <<< "$UNTRACKED_FILES" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| } | hash_stdin | ||||||||||||||||||||||||||||||||||
| )" | ||||||||||||||||||||||||||||||||||
| GHOSTTY_KEY="${GHOSTTY_SHA}-dirty-${DIRTY_HASH}" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| CACHE_ROOT="${CMUX_GHOSTTYKIT_CACHE_DIR:-$HOME/.cache/cmux/ghosttykit}" | ||||||||||||||||||||||||||||||||||
| CACHE_DIR="$CACHE_ROOT/$GHOSTTY_KEY" | ||||||||||||||||||||||||||||||||||
| CACHE_XCFRAMEWORK="$CACHE_DIR/GhosttyKit.xcframework" | ||||||||||||||||||||||||||||||||||
| LOCAL_XCFRAMEWORK="$PROJECT_DIR/ghostty/macos/GhosttyKit.xcframework" | ||||||||||||||||||||||||||||||||||
| LOCAL_KEY_STAMP="$LOCAL_XCFRAMEWORK/.ghostty_state_key" | ||||||||||||||||||||||||||||||||||
| LEGACY_LOCAL_SHA_STAMP="$LOCAL_XCFRAMEWORK/.ghostty_sha" | ||||||||||||||||||||||||||||||||||
| LOCK_DIR="$CACHE_ROOT/$GHOSTTY_KEY.lock" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| mkdir -p "$CACHE_ROOT" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| echo "==> Ghostty build key: $GHOSTTY_KEY" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| LOCK_TIMEOUT=300 | ||||||||||||||||||||||||||||||||||
| LOCK_START=$SECONDS | ||||||||||||||||||||||||||||||||||
| while ! mkdir "$LOCK_DIR" 2>/dev/null; do | ||||||||||||||||||||||||||||||||||
| if (( SECONDS - LOCK_START > LOCK_TIMEOUT )); then | ||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Do not delete the cache lock solely because this process waited >300s; it can remove an active lock and allow concurrent GhosttyKit builds/copies. Prompt for AI agents |
||||||||||||||||||||||||||||||||||
| echo "==> Lock stale (>${LOCK_TIMEOUT}s), removing and retrying..." | ||||||||||||||||||||||||||||||||||
| rmdir "$LOCK_DIR" 2>/dev/null || rm -rf "$LOCK_DIR" | ||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+96
to
+100
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid deleting potentially live locks after timeout. At Line 98-100, a waiting process force-removes the lock directory after 300s. A legitimate long build can exceed that and get its live lock deleted, allowing concurrent cache writes for the same key. Suggested fix LOCK_TIMEOUT=300
LOCK_START=$SECONDS
+LOCK_OWNER_PID_FILE="$LOCK_DIR/pid"
while ! mkdir "$LOCK_DIR" 2>/dev/null; do
+ if [[ -f "$LOCK_OWNER_PID_FILE" ]]; then
+ read -r lock_pid < "$LOCK_OWNER_PID_FILE" || lock_pid=""
+ if [[ -n "$lock_pid" ]] && ! kill -0 "$lock_pid" 2>/dev/null; then
+ echo "==> Removing orphaned GhosttyKit cache lock (pid $lock_pid)..."
+ rm -rf "$LOCK_DIR"
+ continue
+ fi
+ fi
if (( SECONDS - LOCK_START > LOCK_TIMEOUT )); then
- echo "==> Lock stale (>${LOCK_TIMEOUT}s), removing and retrying..."
- rmdir "$LOCK_DIR" 2>/dev/null || rm -rf "$LOCK_DIR"
- continue
+ echo "error: timed out waiting for GhosttyKit cache lock for $GHOSTTY_KEY" >&2
+ exit 1
fi
echo "==> Waiting for GhosttyKit cache lock for $GHOSTTY_KEY..."
sleep 1
done
-trap 'rmdir "$LOCK_DIR" >/dev/null 2>&1 || true' EXIT
+echo "$$" > "$LOCK_OWNER_PID_FILE"
+trap 'rm -rf "$LOCK_DIR" >/dev/null 2>&1 || true' EXITAlso applies to: 105-105 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
| echo "==> Waiting for GhosttyKit cache lock for $GHOSTTY_KEY..." | ||||||||||||||||||||||||||||||||||
| sleep 1 | ||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+95
to
+104
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
After the lock is forcibly removed at line 96 ( Reset
Suggested change
|
||||||||||||||||||||||||||||||||||
| trap 'rmdir "$LOCK_DIR" >/dev/null 2>&1 || true' EXIT | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if [[ -d "$CACHE_XCFRAMEWORK" ]]; then | ||||||||||||||||||||||||||||||||||
| echo "==> Reusing cached GhosttyKit.xcframework" | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| LOCAL_KEY="" | ||||||||||||||||||||||||||||||||||
| if [[ -f "$LOCAL_KEY_STAMP" ]]; then | ||||||||||||||||||||||||||||||||||
| LOCAL_KEY="$(cat "$LOCAL_KEY_STAMP")" | ||||||||||||||||||||||||||||||||||
| elif [[ -f "$LEGACY_LOCAL_SHA_STAMP" ]]; then | ||||||||||||||||||||||||||||||||||
| LOCAL_KEY="$(cat "$LEGACY_LOCAL_SHA_STAMP")" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if [[ -d "$LOCAL_XCFRAMEWORK" && "$LOCAL_KEY" == "$GHOSTTY_KEY" ]]; then | ||||||||||||||||||||||||||||||||||
| echo "==> Seeding cache from existing local GhosttyKit.xcframework (build key matches)" | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| echo "==> Building GhosttyKit.xcframework (this may take a few minutes)..." | ||||||||||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||||||||||
| cd ghostty | ||||||||||||||||||||||||||||||||||
| zig build -Demit-xcframework=true -Dxcframework-target=universal -Doptimize=ReleaseFast | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| echo "$GHOSTTY_KEY" > "$LOCAL_KEY_STAMP" | ||||||||||||||||||||||||||||||||||
| echo "$GHOSTTY_SHA" > "$LEGACY_LOCAL_SHA_STAMP" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if [[ ! -d "$LOCAL_XCFRAMEWORK" ]]; then | ||||||||||||||||||||||||||||||||||
| echo "Error: GhosttyKit.xcframework not found at $LOCAL_XCFRAMEWORK" >&2 | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| TMP_DIR="$(mktemp -d "$CACHE_ROOT/.ghosttykit-tmp.XXXXXX")" | ||||||||||||||||||||||||||||||||||
| mkdir -p "$CACHE_DIR" | ||||||||||||||||||||||||||||||||||
| cp -R "$LOCAL_XCFRAMEWORK" "$TMP_DIR/GhosttyKit.xcframework" | ||||||||||||||||||||||||||||||||||
| rm -rf "$CACHE_XCFRAMEWORK" | ||||||||||||||||||||||||||||||||||
| mv "$TMP_DIR/GhosttyKit.xcframework" "$CACHE_XCFRAMEWORK" | ||||||||||||||||||||||||||||||||||
| rmdir "$TMP_DIR" | ||||||||||||||||||||||||||||||||||
| echo "==> Cached GhosttyKit.xcframework at $CACHE_XCFRAMEWORK" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| echo "==> Creating symlink for GhosttyKit.xcframework..." | ||||||||||||||||||||||||||||||||||
| ln -sfn "$CACHE_XCFRAMEWORK" GhosttyKit.xcframework | ||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -279,6 +279,8 @@ if [[ -z "$TAG" ]]; then | |||||
| exit 1 | ||||||
| fi | ||||||
|
|
||||||
| "$PWD/scripts/ensure-ghosttykit.sh" | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Consider deriving
Suggested change
Or, since SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"and then call: "$SCRIPT_DIR/ensure-ghosttykit.sh" |
||||||
|
|
||||||
| if should_skip_ghostty_cli_helper_zig_build; then | ||||||
| if [[ "${CMUX_SKIP_ZIG_BUILD:-}" != "1" ]]; then | ||||||
| echo "Auto-enabling CMUX_SKIP_ZIG_BUILD=1 for Ghostty CLI helper (${AUTO_SKIP_ZIG_BUILD_REASON})" | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.