SwiftSlash icon indicating copy to clipboard operation
SwiftSlash copied to clipboard

Unable to execute "getting started" commands

Open SimonMcFarlane opened this issue 1 year ago • 6 comments

I'm just looking into using SwiftSlash and am having trouble with getting any commands to execute.

do {
    let command = try Command("ps", arguments: ["aux"])
    let commandResult = try await command.runSync()
    
    if (commandResult.exitCode == 0) {
        let data = commandResult.stdout[0]
        print("data: \(data)")
    } else {
        print("exitCode: \(commandResult.exitCode)")
    }
} catch {
    print("error: \(error)")
}

This command (along with any others I've tried) results in the resourceUncertainty error.

I can see that this error is only thrown when getfdlimit(&utilized, &limit)(of ProcessSpawner.swift - line #376) returns a value other than 0. On my machine this is always coming back with a value of 5. I'm assuming getfdlimit is for getting the file descriptor limit but not sure where to go from here or work out what the underlying issue is.

Machine: MacBook Pro M2 macOS: 13.2.1 Xcode: 14.2 SwiftSlash: 3.4.0

SimonMcFarlane avatar Jun 01 '23 16:06 SimonMcFarlane

Interesting.....this project was forged from needs I had in backend processes on Linux. I never considered that people may take this and try to run it in a MacOS sandbox. But it appears that is what you have done here. And with this use-case in mind, its hard to imagine how SwiftSlash would work.

Overall, you are looking in the right places and definitely have the right understanding of the problem.

SwiftSlash does a brief "safety dance" for each command that is launched, to ensure the system is able to safely facilitate another concurrent command. One of the first steps of this "safety dance" is throwing, because SwiftSlash cannot read /dev/fd, which it uses to count vacant file descriptors based against the systems soft limit.

Even if I am to omit (or fix) this safety step, SwiftSlash still will not run, beause ps is a command that exists outside your sandbox.

If I carry a blind assumption that fork() is allowed in the MacOS sandbox (a very bad and very blind assumption), the only commands SwiftSlash would be able to run are binaries you precompile and bundle into your application directly.

Sadly, SwiftSlash is subject to sandboxing just like any other library - and while it's not an issue for most libraries, it's (indeed) a huge problem for a shell scripting library. Its just the nature of the beast.

tannerdsilva avatar Jun 02 '23 00:06 tannerdsilva

I should document that this use case is not supported (unless you're willing to ship an embedded shell, with additional binaries, as a resource in your app. In which case, there is a slightly nonzero % chance it works).

tannerdsilva avatar Jun 02 '23 00:06 tannerdsilva

Thinking I'm closer to closing this ticket. Probably the only reason its not closed is because I'm carrying this vague notion that perhaps I should deliberately check for the sandbox and throw a fatalError just to make things as clear as possible.

Maybe this is a little reckless but its hard to imagine how else I could clarify this failure path for devs.

tannerdsilva avatar Jul 28 '23 02:07 tannerdsilva

re: sandbox, would this be possible through a helper app? https://developer.apple.com/documentation/xcode/embedding-a-helper-tool-in-a-sandboxed-app

ewhitley avatar Aug 01 '23 13:08 ewhitley

That doesn’t look practical for a cross platform Swift package.

If you are serious about going that route, you should fork SwiftSlash and convert it into an Xcode project that only runs on MacOS. Because it looks like the work to do that would be a project just by itself.

tannerdsilva avatar Aug 15 '23 22:08 tannerdsilva

This issue will close with the release of the v4.0.0 update. In this release, when built in a debug configuration, SwiftSlash check for the environment variable APP_SANDBOX_CONTAINER_ID and throw a fatal error if a value is found under this key.

tannerdsilva avatar Sep 05 '23 15:09 tannerdsilva