Skip to content

Replace polling waitForProcess with Process.terminationHandler bridge #1

@poolcamacho

Description

@poolcamacho

Context

GitService.waitForProcess(_:timeout:) currently polls process.isRunning in a loop with Thread.sleep(0.05) on a global concurrent queue. That burns a CPU slot and ties up a worker thread for the entire duration of every git command (which adds up: every refresh fans out to status, log, branches, currentBranch, stash list).

Suggested by feedback on r/swift.

Proposal

Bridge Process.terminationHandler directly into a withCheckedContinuation. Process fires the handler the instant the child exits, so no polling is needed. Race it against a Task.sleep-based timeout that calls process.terminate() and resumes with false.

Sketch:

func waitForProcess(_ process: Process, timeout: TimeInterval) async -> Bool {
    await withCheckedContinuation { continuation in
        let lock = NSLock()
        var resumed = false
        func resumeOnce(_ value: Bool) {
            lock.lock(); defer { lock.unlock() }
            guard !resumed else { return }
            resumed = true
            continuation.resume(returning: value)
        }

        let timeoutTask = Task {
            try? await Task.sleep(for: .seconds(timeout))
            if process.isRunning { process.terminate() }
            resumeOnce(false)
        }

        process.terminationHandler = { _ in
            timeoutTask.cancel()
            resumeOnce(true)
        }
    }
}

The locking is needed because terminationHandler and the timeout task can race.

Acceptance criteria

  • Replace the polling loop in Services/GitService.swift
  • All existing tests / build still pass
  • Manual smoke test: open a repo, perform a few commits / pushes, observe Activity Monitor no longer shows extra busy threads while git is running

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions