Closed steprescott closed 1 month ago
Hello!
First, regular support for my packages is completely free! But, if you are looking for more dedicated blocks of time, I absolutely do that as well.
I have come into an issue when calling try await server.diagnostics(diagnosticParams) when the executable is ran from an Xcode command plugin.
Hmm, I would have expected plugins like this to be sandboxed. If the execution environment is the only thing you are changing, I'm worried about that. I would be surprised if any LSP server could run sandboxed, even sourcekit-lsp. But maybe!
However, the server does respond to the init message from within the plugin so I know it's not due to incorrect configuration of the plugin.
Let's dig into this as well, to be sure we are sure this is happening. LSPClient does a lot of stuff lazily, so it can be hard sometimes to understand what it is doing, when.
Also, not that it's relevent to the problem at hand, but I did glance and see some semaphore usage that could be problematic in the example.
Hey. Thanks for your quick reply.
The way I validated that the init message was received was by adding a print into the initializeIfNeeded
function.
extension InitializingServer {
/// Run the initialization sequence with the server, if it has not already happened.
public func initializeIfNeeded() async throws -> InitializationResponse {
switch state {
case .initialized(let initResp):
return initResp
case .uninitialized, .shutdown:
try await semaphore.waitUnlessCancelled()
}
defer { semaphore.signal() }
let params = try await initializeParamsProvider()
let initResponse = try await channel.initialize(params)
print("💻 INIT:", initResponse)
try await channel.initialized(InitializedParams())
self.state = .initialized(initResponse)
capabilitiesContinuation.yield(initResponse.capabilities)
return initResponse
}
...
}
Yer semaphores can be run but I've used this in the past to move halt the process. Maybe I'll change that to use https://github.com/groue/Semaphore but it's very basic usage.
I have other operations that occur within the Xcode command plugin that operate over files and I can mutate them. I'll do some more verification on the question about sandboxing. However the ability to change files and the init call working leads me to think it is not sandboxed.
No worries!
Ok, good that was smart. I'm still very suspicious of the server's runtime environment, though. Especially since a) I know that the LSP protocol wasn't built to support sandboxing and b) pretty much ever server I have tried explodes when run that way.
Sourcekit-lsp might be different though, I honestly don't know. It is possible it does not have external dependencies, and the plugin system probably does forward along permissions to access opened files. Or maybe these things aren't sandboxed?
Can you post some of the crash report?
Oh, also DispatchSemaphore and https://github.com/groue/Semaphore have similar names but are actually not interchangeable. You were using DispatchSemaphore to synchronously wait for an async operation. Very common problem, but unfortunately this is something the concurrency system explicitly does not support. I've had to deal with this too, occasionally, and it is a very challenging problem that does not always have viable solutions...
I don't get a crash report unfortunately. I've just noticed that main
has more commits than the latest release and will try that. I will also try linking your package locally to the example project.
Ohh, sorry, I assumed that uncaught signal was a crash somewhere. Can you just double-check that there's nothing being generated in Console.app > Crash Reports?
Great advice!
So there does seem to be an error in the console. Does suggest sandboxing.
Sandbox: sourcekit-lsp(15080) deny(1) mach-lookup com.apple.CoreServices.coreservicesd
Pretty sure sourcekit-lsp is being run in a sandbox here and it cannot tolerate that...
I haevn't be able to put too much time into this recently, but I've done quite a lot of work on running servers in a sandboxed environment. Here's one effort: https://github.com/ChimeHQ/LanguageServerScripts
~Might be out of the scope of this issue, but would perhaps notarizing the binary help?~ I don't think it will.
I'll have a look at your linked repo.
It's so strange that the init is allowed or have I misunderstood that?
In my experience, this is kind of how it goes. They are kinda functional, but they have some external dependencies that don't work. So the failures only occur once you ask them to do something that isn't allowed by the sandbox.
I'll close the issue. Thanks for your help. If you do have other ideas or progress with ways that can run outside the sandbox please do let this issue know.
Yup, process is sandboxed.
I have been able to get the results from sourcekit-lsp
by using https://github.com/codeface-io/LSPService. So having a local server that proxies sourcekit-lsp
Ahh yes! I've worked with the author a bit on this exact problem. We were hoping to collaborate some more, but so far, it hasn't happened.
Thank you for your work over
sourcekit-lsp
. I did start at writing my own client but then came across this and it really accelerated my development!I have come into an issue when calling
try await server.diagnostics(diagnosticParams)
when the executable is ran from an Xcode command plugin.In the video below you can see that when I run the Xcode command plugin, by right mouse clicking on the App project and selecting my LSP plugin, the
lsp
executable is triggered but the server is terminated as soon asdiagnostics
is called. However, the server does respond to the init message from within the plugin so I know it's not due to incorrect configuration of the plugin.When I look to the termination reason I see it is
2
aka,uncaughtSignal
with a status of5
. But that is as far as I have been able to debug so far. Within the same video you can see when I run thelsp
command from Xcode or via terminal it correctly outputs the errors found in thetextDocument
.I would appreciate your help and happy to pay for your time too.
I have attached a
.zip
file that has an example app that is just an unmodifiedFile > New Project
that links the local Swift Package ofLSP
. TheLSP
package holds the command that when ran callsdiagnostics
and a plugin that calls thelsp
binary.Happy to answer any questions or do any further tasks that might support the investigation.
https://github.com/user-attachments/assets/13012c48-c9fa-48a3-ab82-ed380f6b097e
Example.zip