Commit Graph

55 Commits

Author SHA1 Message Date
Alex Hoppen
7f90508e51 Add a document to describe which log level to use
Also change a few log levels and make all log messages consistently start with an uppercase letter.
2024-06-11 12:01:50 -07:00
Alex Hoppen
7a65050c33 Don’t fatalError if encoding a message to the client could not be encoded 2024-04-04 11:05:53 -07:00
Alex Hoppen
be42621f4c Don’t crash sourcekit-lsp if a known message is missing a field
Previously, we `fatalError`ing when `JSONDecoder` failed to decode a message from the client. Instead of crashing, try recovering from such invalid messages as best as possible. If we know that the state might  have gotten out of sync with the client, show a notification message to the user, asking them to file an issue.

rdar://112991102
2024-04-02 07:50:03 +02:00
Alex Hoppen
6edc462d09 Remove --sync option
With the `test-sourcekit-lsp.py` integration test rewritten to not use `--sync`, there are no more users of this option. Remove it since we don’t really test it anyway.
2024-03-22 08:45:57 +01:00
Alex Hoppen
d1b527e14c Make the LanguageServerProtocolJSONRPC module build with strict concurrency enabled 2024-03-20 08:37:39 +01:00
Alex Hoppen
259da4554e Improve queue handling in JSONRPCConnection
This started off by guarding `state` against concurrent access and then escalated slightly.

The main changes are:
- `state` must only be accessed on `queue` now, preventing race conditions of message handling while the connection is being closed.
- A few functions were renamed, merged, and documented to simplify the code
- A few dead members were removed
2024-03-20 08:30:16 +01:00
Alex Hoppen
3007d9f392 Naming improvements, added comments and typo fixes in connection related code
This should make the code easier to understand. No functionality change.
2024-03-20 08:30:16 +01:00
Alex Hoppen
7c46df3abe Remove clientID from request handling
The client ID was needed when a `MessageHandler` could handle messages from multiple connections. We don’t support this anymore (because it wasn’t needed) and so the client ID doesn’t need to get passed through as well.
2024-03-20 08:28:26 +01:00
Alex Hoppen
757a029664 Log messages from the build server and clangd
Log messages sent to clangd and the build server in a similar way that we log requests to sourcekitd.

Fixes #886
rdar://116705677
2023-12-12 14:05:25 -08:00
Alex Hoppen
f960d7ed9b Change logging to use OSLog
OSLog is the suggesting logging solution on Apple platforms and we should be using it there, taking advantage of the different log levels and privacy masking.

Switch sourcekit-lsp to use OSLog on Apple platforms and implement a logger that is API-compatible with OSLog for all uses in sourcekit-lsp and which can be used on non-Darwin platforms.

The goal of this commit is to introduce the new logging API. There are still improvements about what we log and we can display more privacy-insensitive information after masking. Those changes will be in follow-up commits.
2023-10-13 13:46:32 -07:00
Alex Hoppen
d0fc00ce98 Format using swift-format
Add `.swift-format` to the repo and format the repo with `swift-format`.

This commit does not add any automation to enforce formatting of sourcekit-lsp in CI. The goal of this commit is to get the majority of source changes out of the way so that the diff of actually enforcing formatting will have fewer changes or conflicts.
2023-10-10 13:44:47 -07:00
Alex Hoppen
4495256b35 Remove the queue parameter from Connection.send
We don’t actually care about the queue that we receive the reply on anymore since we migrated everything™ to actors/async/await.
2023-10-06 18:07:20 -07:00
Andrey Klebanov
e441299449 Addressed code review comments:
- change closeHandler's type to optional

Issue: #852 closeHandler callback can be nil in an initializer
2023-10-05 11:31:13 -04:00
Andrey Klebanov
785b00c438 Don't call closeHandler if it is nil
Issue: #852 closeHandler callback can be nil in an initializer
2023-10-04 20:14:09 -04:00
Alex Hoppen
1f02b95e55 Shift responsibility for in-order message handling from Connection to SourceKitServer
This generally seems like the cleaner design because `SourceKitServer` is actually able to semantically inspect the message and decide whether it can be handled concurrently with other requests.
2023-10-03 07:56:49 -07:00
Alex Hoppen
edfda7d743 Add support for concurrent queues and dispatch barriers to AsyncQueue 2023-10-03 07:56:49 -07:00
Alex Hoppen
34c6b81295 Move semaphore signalling to block main thread until request has received a reply instead of until it has been handled
This was causing the sourcekit-lsp integration test to fail.
2023-10-02 09:45:27 -07:00
Alex Hoppen
09dc0bc82f Make SourceKitServer an actor
Unfortuantely, we have a few potential out-of-order exeuction possibilities while we migrate everything else to also be asyncronous. But those should be low-probability issues that we can fix in follow-up commits, so I think it’s fine for now. All of these places are marked with `FIXME: (async)`
2023-10-02 09:43:42 -07:00
Alex Hoppen
ce58b3b2a5 Make MessageHandler.handle async
This is the prerequisite for making `SourceKitServer` an actor, which will mean that the `handle` methods will be `async`.

The current paradigm of returning from `handle` once we can guarantee that there’s no out-of-order execution and then returning the actual result via the callback that’s attached to `Request` is a little weird still. I am hoping to change this paradigm to return the actual result and have a callback function that `handle` can call to indicate that it’s ready to accept another message while guaranteeing in-order execution, essentially flipping the role of the return value and the closure callback. But that’s something to be done after the entire stack has been asyncificied.
2023-10-02 09:43:39 -07:00
Alex Hoppen
9ec614942a Handle messages on a serial queue in Connection
When we switch `SourceKitServer`, `SwiftLanguageServer` etc. to be actors, we can’t rely on them to provide ordering guarantees anymore because Swift concurrency doesn’t provide any ordering guarantees.

What we should thus do, is to handle all messages on a serial queue on the `Connection` level. This queue will be blocked from handling any new messages until a message has been sufficiently handled to avoid out-of-order handling of messages. For sourcekitd, this means that
a request has been sent to sourcekitd and for clangd, this means that we have forwarded the request to clangd.

Note that this serial queue is not the main thread, so we will continue accepting data over stdin, just the handling of those messages is blocked.
2023-10-02 09:43:36 -07:00
Alex Hoppen
b22af35eb1 Revert asyncificaiton changes
The asyncification changes caused some non-deterministic test failures. I believe that some of these are due to race conditions that are the result of the partial transition to actors.

Instead of merging the asyncification piece by piece, I will collect the changes asyncification changes in a branch and then qualify that branch througougly (running CI multiple times) before merging it into `main`.
2023-09-30 10:09:59 -07:00
Alex Hoppen
70f9903144 Move semaphore signaling to block main thread until request has received a reply instead of until it has been handled
This was causing the sourcekit-lsp integration test to fail.
2023-09-28 22:28:50 -07:00
Ben Barham
5b8c034f9d Revert "Fix the --sync option of sourcekit-lsp"
This reverts commit ed45b26221.
2023-09-28 15:48:26 -07:00
Alex Hoppen
ed45b26221 Fix the --sync option of sourcekit-lsp
We were waiting for the semaphores outside of the `messageHandlingQueue`, which means that we didn’t actually block the message handling queue until the previous request received a result, effectively rendering `--sync` useless.
2023-09-28 08:28:36 -07:00
Alex Hoppen
351eaa2393 Make SourceKitServer an actor
Unfortuantely, we have a few potential out-of-order exeuction possibilities while we migrate everything else to also be asyncronous. But those should be low-probability issues that we can fix in follow-up commits, so I think it’s fine for now. All of these places are marked with `FIXME: (async)`
2023-09-27 09:48:21 -07:00
Alex Hoppen
0e5d5c9fda Make MessageHandler.handle async
This is the prerequisite for making `SourceKitServer` an actor, which will mean that the `handle` methods will be `async`.

The current paradigm of returning from `handle` once we can guarantee that there’s no out-of-order execution and then returning the actual result via the callback that’s attached to `Request` is a little weird still. I am hoping to change this paradigm to return the actual result and have a callback function that `handle` can call to indicate that it’s ready to accept another message while guaranteeing in-order execution, essentially flipping the role of the return value and the closure callback. But that’s something to be done after the entire stack has been asyncificied.
2023-09-27 09:47:51 -07:00
Alex Hoppen
7c0a910358 Handle messages on a serial queue in Connection
When we switch `SourceKitServer`, `SwiftLanguageServer` etc. to be actors, we can’t rely on them to provide ordering guarantees anymore because Swift concurrency doesn’t provide any ordering guarantees.

What we should thus do, is to handle all messages on a serial queue on the `Connection` level. This queue will be blocked from handling any new messages until a message has been sufficiently handled to avoid out-of-order handling of messages. For sourcekitd, this means that
a request has been sent to sourcekitd and for clangd, this means that we have forwarded the request to clangd.

Note that this serial queue is not the main thread, so we will continue accepting data over stdin, just the handling of those messages is blocked.
2023-09-27 09:47:51 -07:00
Alex Hoppen
ca45a7a62b Return a .serverCancelled error code if the server cancels a request
`.cancelled` should only be returned if the client requested cancellation.
2022-12-05 08:45:36 +01:00
Saleem Abdulrasool
223f98906e LanguageServerProtocolJSONRPC: avoid failing cast on Windows
This error code is poorly mapped on Windows and results in a runtime
failure.  Avoid the cast to improve stability.
2022-09-25 08:53:32 -07:00
Alex Hoppen
ee53f858c5 Globally ignore SIGPIPE on Linux
We receive a `SIGPIPE` if we write to a pipe that points to a crashed process. This in particular happens if the target of a `JSONRPCConnection` has crashed and we try to send it a message.
On Darwin, `DispatchIO` ignores `SIGPIPE` for the pipes handled by it, but that features is not available on Linux.
Instead, globally ignore `SIGPIPE` on Linux to prevent us from crashing if the `JSONRPCConnection`'s target crashes.

Fixes rdar://75580936
2021-03-22 22:40:47 +01:00
Ben Langmuir
bb9560f2e2 Merge pull request #341 from compnerd/handling
Fix the Pipe handling on Windows to be correct
2020-11-02 11:56:06 -08:00
Saleem Abdulrasool
6a275d134c Fix the Pipe handling on Windows to be correct
This actually addresses the real issue that was ignored earlier about
pipes on Windows.  The FileHandle cannot provide a non-owning file
descriptor (the returned file descriptor would need to be explicitly
`_close`'d by the receiver).  Foundation now vends a `_handle` accessor
to the OS primitive handle.  Use this to create the dispatch loop for
messaging.  We now create the JSONRPCConnection from handles on Windows
which actually should help enable running some of the tests on Windows
as well.
2020-11-02 09:55:58 -08:00
Sebastian Fichtner
7a36a51014 Synchronously send error response on message decoding failure (#334)
* Replaces two logs since those don't result in response messages anymore
* Adds a func for sending messages synchronously, to get the two messages out before fatalError
2020-10-16 16:29:46 -07:00
flowtoolz
0427823d74 Log error before fatalError(...) when message decoding fails 2020-10-13 15:33:59 +02:00
Saleem Abdulrasool
b33a5171cc LanguageServerProtocolJSONRPC: make Windows path work
This adjusts the use of Dispatch to build on Windows.  Windows does not
provide `stdout_fileno` and `stderr_fileno`.  However, it is possible to
use `fileno` to get the associated fileno from the descriptor.

Dispatch on Windows does not deal with fd's but rather with handles.
Convert the file descriptor to a handle and pass that off to dispatch.
The handle is a non-owning reference, and should not be closed.
Fortunately, dispatch does not close the handle when the DispatchIO is
closed.
2020-09-29 13:48:06 -07:00
Ben Langmuir
fae2fe85a7 [JSONRPC] Do not exit until outstanding I/O has finished
Specifically, we care that all outstanding **writes** are finished
before we call the close handler, because otherwise we may (a) send
corrupted output during shutdown, or (b) drop notifications and replies
sent during the shutdown process.  The former is a potential issue for
clients that are not robust about parse failures, and the latter is an
issue for reproducibility and robustness during testing/debugging - in
particular, we have some integration tests that send data without
waiting for individual replies and they need to finish outstanding
replies before exiting.

rdar://60159448
2020-03-10 11:16:34 -07:00
Alex Hoppen
f167126c8d Fix typo: JSONRPCConnection should be spelled with two 'n' 2019-11-29 10:20:02 -08:00
Ben Langmuir
dfe2a6bc76 [jsonrpc] Move close handler to start
Since the connection and message handler have a reciprocal need to know
about each other, move the closeHandler so that it has the opportunity
to call a method on the message handler if desired.
2019-11-21 11:56:37 -08:00
Ben Langmuir
775e198f77 Rename LSPSupport -> LSPLogging to reflect reduced scope
Ideally we can someday migrate this to something more standard such as
swift-log, and make it explicit how to control logging for the JSONRPC
module.
2019-11-19 11:08:31 -08:00
Alex Hoppen
05ecd26d08 Reorganize the repository into a set of bare LSP modules and SourceKit modules
We will be able to split the LSP modules off later. These LSP modules
will provide the ability to write custom LSP servers and clients in
Swift. The sourcekit-lsp repository will build on top of this new
package to provide an LSP implementation that creates a language server
for Swift and C-based-languages.
2019-11-14 10:35:06 -08:00
Alex Hoppen
4b3c571db6 Eliminate _IndirectConnection and replace it by closure
This allows us to move the semaphore logic out of the message to the connection where it belongs.
2019-11-12 15:04:44 -08:00
Ben Langmuir
3a99dddb98 Fix hang/crash when a write failure occurs
This code was doing a sync dispatch to a queue it was already running
on. Instead, go through the same path as other close calls.  This would
hang, or if you're lucky crash when dispatch detects the issue.
2019-10-17 16:51:34 -07:00
Ben Langmuir
cac8f8d77f [tsan] Fix race on close in JSONRPCConnection 2019-10-10 14:05:49 -07:00
Ben Langmuir
a5d5d09695 [jsonrpc] Fix race between close() and EOF
We implicitly close the connection when the input file descriptor is
closed, or if it has an error. But we also close things down explicitly
when we see the exit notification. We need to protect against a race
triggering us to call the close handler multiple times. This was
resulting in `sourcekit-lsp` racing to call `exit(0)`, which triggered a
double-free and abort on Linux.
2019-08-23 14:03:47 -07:00
Ben Langmuir
e6fc0f017b [cli] Add --sync option for testing
When testing the sourcekit-lsp binary, it is handy to be able to force
requests to be handled synchronously. This only affects the protocol
layer, not the implementation. This option is hidden from the help text
and should only be used for testing/debugging.
2019-08-22 16:19:36 -07:00
Richard Howell
93982b2f2a messageRegistry -> protocol 2019-08-16 19:18:29 -07:00
Richard Howell
3701f6dcd5 pass in message registry instead of singleton 2019-08-15 15:28:19 -07:00
Ben Langmuir
65b98b383c Remove testable imports of LanguageServerProtocolJSONRPC 2019-08-08 22:22:50 -07:00
Ben Langmuir
ddd096f019 Rename JSONRPCMessageHeader and methods in preparation for making public 2019-08-08 22:14:57 -07:00
Ben Langmuir
119b3fa1cb Rename Message -> JSONRPCMessage in preparation for making it public 2019-08-08 22:06:07 -07:00