Mastering Multi-Process Debugging in Xcode: A Script to Attach to All Matching Processes

For most iOS developers, debugging boils down to a single process: the main app binary. But Mac developers often juggle XPC services and custom subprocesses, demanding more flexible tools. Xcode's built-in "Debug XPC Processes" checkbox offers a lifeline for auto-attaching to an app's XPC services, but its limitations—failing to handle non-XPC subprocesses or multiple instances—can grind workflows to a halt.

![Main article image](


alt="Article illustration 1"
loading="lazy">

)

Xcode's XPC Debugging: Convenient but Limited

In the scheme editor's "Options" tab under "Run Action," enabling "Debug XPC Processes" automatically attaches the debugger when an XPC service launches. This shines in projects like the open-source Sparkle framework, where XPC services handle software updates.


alt="Article illustration 2"
loading="lazy">

captures this in action: Xcode seamlessly attaches to Sparkle's "org.sparkle-project.InstallerLauncher" alongside the main MarsEdit app.

Yet, caveats abound. Xcode skips third-party XPC services, like those in WebKit, unless you built them locally. Worse, it ignores non-XPC subprocesses entirely. Apps like FastScripts, which spawn isolated "RSScriptRunner" processes for parallel AppleScript execution, force manual intervention via "Debug > Attach to Process by PID or Name."


alt="Article illustration 3"
loading="lazy">

shows this tedious step: typing the process name and hoping for success. But with FastScripts maintaining multiple "RSScriptRunner" instances for efficiency—one always ready, others handling concurrent scripts—Xcode attaches only to the first match, leaving others in the dark.

The AppleScript Solution: Attach to All

Daniel Jalkut, indie developer behind MarsEdit and FastScripts, engineered a simple AppleScript to conquer this. It prompts for a process name, fetches all matching PIDs via System Events, and commands Xcode to attach to each—without suspending them.

Here's the script:

set processName to text returned of (display dialog "Enter process name:" default answer "")

set processIDs to {}
tell application "System Events"
    set processIDs to unix id of every process whose name is processName
end tell

tell application "Xcode"
    repeat with processID in processIDs
        tell workspace document 1
            attach to process identifier processID without suspended
        end tell
    end repeat
end tell

Running it on "RSScriptRunner" results in Xcode debugging all instances at once.


alt="Article illustration 4"
loading="lazy">

illustrates four such processes attached alongside FastScripts' main app. Breakpoints now trigger across any hitting process, supercharging multi-process debugging.

Implications for Mac Development

This workaround underscores a gap in Xcode: no native support for auto-attaching to all child processes or regex-matched ones. Jalkut hopes Apple expands the feature, but until then, this script empowers developers building resilient, parallel-processing apps. For teams scaling subprocesses in utilities, update mechanisms, or sandboxed components, it's a productivity booster—proving community ingenuity often bridges enterprise tool shortcomings.

Source: IndieStack blog post by Daniel Jalkut