Motivation
* `check_benchmark_thresholds.sh` was updated to check for exit code 2
from `swift package benchmark thresholds check` to distinguish
threshold regression from build errors.
* It seems SwiftPM's `CommandPlugin` infrastructure always exits with code 1 when
`performCommand` throws, regardless of the error's raw value. So the
exit code is never 2, causing all regressions to fall through to the
`else` branch and be misreported as build errors, with no diff output.
Modifications
* Remove the `rc == 2` check and instead attempt `thresholds update`
for any non-zero `rc` from `thresholds check`.
* Use the result of `thresholds update` to distinguish regression
(success) from build error (failure).
* Remove `--exit-code` from `git diff` to prevent `set -uo pipefail`
from aborting the script before output is fully flushed.
Result
* Benchmark threshold regressions correctly output the `=== BEGIN DIFF
===` section again.
* Actual build errors are still correctly detected and reported.
Motivation
* `@main` references to `swiftlang/github-workflows` are deprecated.
Modifications
* Replace `@main` with `@0.0.7` in all workflow files.
Result
* Workflow files reference a pinned version of
`swiftlang/github-workflows`.
Adds capability to NIOFS to copy regular files and symlink, allowing to
overwrite the destination.
### Motivation:
Per https://github.com/apple/swift-nio/issues/3403 and
https://github.com/apple/swift-nio/pull/3470 we want to add
`replaceExisting: bool` to `FileSystem.copyItem`.
### Modifications:
1. Adds `replaceExisting: bool` parameter to
`FileSystemProtocol.copyItem`.
2. Adds `replaceExisting: bool` parameter to `FileSystem.copyItem` and
implementation for regular files and symbolic links.
3. Adds tests.
---------
Co-authored-by: George Barnett <gbarnett@apple.com>
## Motivation
NIO channels abstract over an underlying transport mechanisms (sockets,
pipes, etc.), which users typically need not interact with. However,
there are scenarios where users need direct access to the underlying
transport for low-level operations that work outside NIOs abstraction.
One example is performing out out-of-band operations on the underlying
file descriptor for a socket-based channel.
This PR adds a structured way to access the underlying transport of a
channel, for channels that choose to implement it.
## Modifications
- Add a new `public protocol
NIOTransportAccessibleChannelCore<Transport>` which provides a scoped
`withUnsafeTransport(_:)`, used for channel implementations to opt-in.
- Add conformance to
`NIOTransportAccessibleChannel<NIOBSDSocket.Handle>` for
`BaseSocketChannel`, to make this API available for all socket-based
channels, including channels returned from the socket-based bootstrap
public APIs.
- Add public API
`ChannelPipeline.SynchronousOperations.withUnsafeTransportIfAvailable(_:)`
Note that not all channels need to or should their transport, which is
why this was added as an additional protocol that refines `ChannelCore`,
vs. extending `Channel` or `ChannelCore` with a default implementation.
The protocol uses a primary associated type allowing channels to provide
typed access to the transport. E.g. this could be used in NIO Transport
Services to expose the underlying `NWConnection`, if desired.
The method itself is spelled with "unsafe", uses scoped access, and has
clear documentation that users must not violated any of NIOs assumptions
about the state of the underlying transport. It's very much not intended
for every day use. It being on `ChannelCore` should defer users of the
low-level API, since `Channel._channelCore` is marked as for NIO
internal use, and the public `withUnsafeTransportIfAvailable(_:)` will
take care of the runtime checks for channels that have opted into this
API.
## Result
- New opt-in API for channel implementations to expose their underlying
transport
- All socket-based channels from NIOPosix now expose the underlying
socket file descriptor
- New API
`ChannelPipeline.SynchronousOperations.withUnsafeTransportIfAvailable(_:)`
for users
---------
Co-authored-by: Agam Dua <agam_dua@apple.com>
### Motivation:
Currently if there is an error in the Benchmark targets, that prevents
the Benchmark to build correctly, we still get a CI success.
### Modifications:
- Check for the threshold changed error
### Result:
- More reliable CI
### Motivation:
SwiftPM behaviour has changed in recent Swift nightlies.
In most recent released version of Swift, SwiftPM will use the parent
directory name for the source and test target directory too, even when
it contains a period:
```
% docker run -it swift:6.2 bash -c 'mkdir -p /tmp/foo.bar && cd /tmp/foo.bar && swift package init'
Creating library package: foo.bar
Creating Package.swift
Creating .gitignore
Creating Sources
Creating Sources/foo.bar/foo_bar.swift
Creating Tests/
Creating Tests/foo.barTests/
Creating Tests/foo.barTests/foo_barTests.swift
```
Note in the above how it replaces the `.` with a `_` in the source
files, but the directories retain the `.`.
In the recent nightly-main, SwiftPM has also started replacing `.` with
`_` in the target directory names:
```
% docker run -it swiftlang/swift:nightly-main bash -c 'cat /etc/motd && mkdir -p /tmp/foo.bar && cd /tmp/foo.bar && swift package init'
################################################################
# #
# Swift Nightly Docker Image #
# Tag: swift-DEVELOPMENT-SNAPSHOT-2026-02-06-a #
# #
################################################################
Creating library package: foo.bar
Creating Package.swift
Creating .gitignore
Creating Sources
Creating Sources/foo_bar/foo_bar.swift
Creating Tests/
Creating Tests/foo_barTests/
Creating Tests/foo_barTests/foo_barTests.swift
```
Probably this
https://github.com/swiftlang/swift-package-manager/pull/9252.
This breaks our CI automation, only on nightly-main, because we run
`swift package init` in a directory created by `mktemp -d`, which, by
default, follows the pattern `tmp.XXXXXXX`.
### Modifications:
Create temporary directory for Swift package using explicit pattern
containing no periods.
### Result:
C++ interop CI should now work again on nightly-main Swift, and continue
to work on all supported Swift versions.
### Motivation
Issue #2773 reports a problem where channels can receive
`channelInactive` before `channelActive`. This breaks expectations and
should not happen. Instead of sending them in the wrong order, this PR
suppresses both of them in those cases.
### Modifications
* Add a test to reproduce the problematic behavior.
* Update the state machine to split the active state into two. This
decouples succeeding the promise from sending the signal. Transiting to
closing only sends `channelInactive` when originating from the state
that sent `channelActive`.
### Result
Address #2773.
Edit: Updated modifications to reflect latests commit.
Adds three new system call wrappers for the `symlinkat`, `renameatx_np`,
and `unlinkat` system calls.
### Motivation:
Related to https://github.com/apple/swift-nio/issues/3403 and
https://github.com/apple/swift-nio/pull/3470. This PR adds syscall
wrappers needed to atomically overwrite existing files or symlinks at
the destination during copy operations. On Linux, atomic overwrites
require a "copy to temp file, then rename" strategy. We use the `*at`
family of syscalls (which operate relative to directory file
descriptors) to avoid TOCTOU race conditions.
### Modifications:
1. Adds three system call wrappers for the `symlinkat`, `renameatx_np`,
and `unlinkat` system calls.
2. Adds related tests
3. Updates the `FileSystemError` for `symlink` and `unlink` to take in
the system call name to allow for the `*at` names to be passed.
### Motivation:
`NIOFileSystem` currently exposes the same API as `_NIOFileSystem`,
which is not API stable. `NIOFileSystem`
was created in error, and its lack of underscore incorrectly implies API
stability. Users who are currently importing `NIOFileSystem` should
ideally move to `_NIOFileSystem`. However this isn't made clear in the
docs:
1. The README talks about the non-underscored `NIOFileSystem`.
2. There are no hosted API docs `NIOFileSystem`.
3. The hosted API docs for `NIO` point to the docs for `NIOFileSystem`
-- results in 404.
### Modifications:
- Update the README to refer to `_NIOFileSystem`.
- Update the hosted API docs for `NIO` to point to docs for
`_NIOFileSystem`.
- Add hosted API docs for `NIOFileSystem` with a statement explaining
the situation and pointing people to the docs
for `_NIOFileSystem`.
### Result:
Clearer documentation on the state and relationship of the
`NIOFileSystem` and `_NIOFileSystem` modules.
Ports NIOThreadPoolTest in NIOPosix from XCTest to Swift Testing.
### Motivation:
Tests should use the latest Swift Testing framework when possible.
### Modifications:
- Ported `NIOThreadPoolTest` from XCTest to Swift Testing
- Updated test implementation from Dispatch to Swift Concurrency as
needed to support test functionality
### Result:
All tests continue to pass, NIOThreadPoolTest now has more modern Swift
Testing syntax.
Port `EventLoopFutureTest` to Swift Testing. Includes some adjustments
to ensure tests are ran from the event loop, among other minor changes
### Motivation:
Tests should use the latest Swift Testing framework when possible.
### Modifications:
- Ported `EventLoopFutureTest ` from XCTest to Swift Testing
- Consolidated instantiations of `EmbeddedEventLoop()` into a private
function called `makeEventLoop` to allow for easier injection of a
different loop from a single location.
- Migrated some `.wait` usages to `.get` to allow tests to run async.
### Result:
All tests continue to pass, EventLoopFutureTest now has more modern
Swift Testing syntax.
We have a number of copies of `UnsafeTransfer` and two copies of
`UnsafeMutableTransferBox` in our code base. Before introducing more of
those, lets centralize to just one using a `package` access modifier.
This PR moves the nightly-next CI to use the 6.3 images. Since those
checks should be non required on any user of this package and the name
of the check doesn't change with moving images this should be a
non-breaking change.
### Motivation:
Channels based on `BaseSocketChannel` throw in both `getOption` and
`setOption` if the channel has been closed, since the `setsockopt` will
fail. However, the current behavior of `EmbeddedChannel` is options
remain writable and readable on closed channels.
There are situations where we'd like to be able to model the runtime
behaviour of the real channel in tests, e.g. to test this fix:
https://github.com/apple/swift-nio-extras/pull/304.
### Modifications:
- Add API to enable throwing in `EmbeddedChannel.getOption` and
`.setOption` if channel is closed.
- Add a test for this new behavior.
### Result:
- New API to enable throwing in `EmbeddedChannel.getOption` and
`.setOption` if channel is closed.
- No observable change for existing users of `EmbeddedChannel`.
### Motivation:
Packages that consume NIOPosix should be able to compile to WASI
platforms without special configurations. This change elides the
NIOPosix source from WASI platforms to simplify configuration.
Without this change:
```swift
dependencies: [
// Without this PR, downstream packages must maintain exhaustive platform list to exclude `.wasi`:
.product(
name: "NIOPosix",
package: "swift-nio",
condition: .when(platforms: [
.macOS,
.macCatalyst,
.iOS,
.tvOS,
.watchOS,
.visionOS,
.driverKit,
.linux,
.windows,
.android,
.openbsd,
// .wasi // <-- Need to exclude this, because there is no exclusion list api for SPM conditionals
])
),
]
```
With this change:
```swift
dependencies: [
// Without this PR, downstream packages can consume NIOPosix simply:
.product(name: "NIOPosix", package: "swift-nio"),
]
```
### Modifications:
- Add compiler directives (`#if !os(WASI)`) to all source files in
NIOPosix
### Result:
Downstream packages can compile to wasm without manually excluding the
NIOPosix dependency.
### Testing performed
- Verified `swift build --swift-sdk wasm32-unknown-wasip1 --target
NIOPosix` compiles, which demonstrates proper elision of source files in
NIOPosix that aren't wasm-ready.
- Confirmed GitHub [checks
pass](https://github.com/PassiveLogic/swift-nio/actions/runs/21151341738).
### Motivation:
Packages that consume NIOEmbedded should be able to compile to WASI
platforms without special configurations. This change elides the
NIOEmbedded source from WASI platforms to simplify configuration.
Without this change:
```swift
dependencies: [
// Without this PR, downstream packages must maintain exhaustive platform list to exclude `.wasi`:
.product(
name: "NIOEmbedded",
package: "swift-nio",
condition: .when(platforms: [
.macOS,
.macCatalyst,
.iOS,
.tvOS,
.watchOS,
.visionOS,
.driverKit,
.linux,
.windows,
.android,
.openbsd,
// .wasi // <-- Need to exclude this, because there is no exclusion list api for SPM conditionals
])
),
]
```
With this change:
```swift
dependencies: [
// Without this PR, downstream packages can consume NIOEmbedded simply:
.product(name: "NIOEmbedded", package: "swift-nio"),
]
```
### Modifications:
- Fix compiler directive using in AsyncTestingChannel.swift to include
an extension
### Result:
Packages can compile to wasm without manually excluding the NIOEmbedded
dependency.
### Testing performed
- Verified `swift build --swift-sdk wasm32-unknown-wasip1 --target
NIOEmbedded` compiles, which demonstrates proper elision of source files
in NIOEmbedded that aren't wasm-ready.
- Confirmed GitHub [checks
pass](https://github.com/PassiveLogic/swift-nio/actions/runs/21151287289).
### Motivation:
In reviewing a copy of this file in swift-log, @czechboy0
[noticed](https://github.com/apple/swift-log/pull/398#discussion_r2685605800)
that the `mutex` variable is essentially unused and unnecessarily
allocated for certain conditions. It is possible the compiler elided
usage. But given the unconditional variable reference in the `deinit`,
the compiler may not be able to.
This change ensures the `mutex` property is completely elided except in
the conditions where it is used.
### Modifications:
- Adjusted compiler directive pattern to completely elide the `mutex`
property for conditions where it would be unused.
- Adjusted `deinit` to avoid referencing `mutex` unless it is compiled
into the `Lock` class
### Result:
The `mutex` property is no longer allocated or even compiled into the
`Lock` class for unsupported configurations. All unit tests and checks
pass.
### Research:
The `deinit` used to have a blanket call to `mutex.deallocate()`. This
has been moved into the platform-specific checks within the `deinit`.
This allows complete elision of the `mutex` property altogether. The
`_runtime(_multithreaded)` condition [appears to be rooted to this
implementation](https://github.com/swiftlang/swift/blob/ffc51b914602765c5d680241796dbd3c3711fa6b/lib/Basic/LangOptions.cpp#L490).
Diving deeper, all [operating systems in this
list](https://github.com/swiftlang/swift/blob/ffc51b914602765c5d680241796dbd3c3711fa6b/lib/Basic/LangOptions.cpp#L554)
except for UnknownOS and WASI result in `_runtime(_multithreaded)`
returning true. That means that `OpenBSD` (and many other operating
systems besides windows) were almost certainly using the `#elseif
(compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) &&
_runtime(_multithreaded))` condition in the `deinit`. In conclusion,
moving `mutex.deallocate()` up into the conditional clauses inside
`deinit` should be identical to the previous implementation for all
operating systems except `llvm::Triple::UnknownOS`. And
`llvm::Triple::UnknownOS` is likely not to have every compiled anyways
due to the [check on line
32](https://github.com/apple/swift-nio/blob/main/Sources/NIOConcurrencyHelpers/lock.swift#L32).
So in summary, it is expected that this clean up will compile identical
to the previous implementation for all platforms except WASI platforms
that don't have pthread support. For non-pthread WASI platforms, the
unused `mutex` is properly elided from compilation altogether.
### Testing Done:
- Confirmed that unit tests pass locally using Xcode
- Verified [PR checks
pass](https://github.com/PassiveLogic/swift-nio/actions/runs/21149729751)
Sequoia runners are no longer available and we need to switch to Tahoe.
### Motivation:
Sequoia runners are no longer available and jobs requesting them hang.
### Modifications:
Request Tahoe runners.
### Result:
Jobs no longer hang, macOS tests and benchmarks are running on Tahoe.
As observed by @kkebo, this was missing from the implementation.
### Motivation:
Correct pthread API usage.
### Modifications:
Initialize the pthread_mutexattr_t with pthread_mutexattr_init before
passed to pthread_mutex_init.
### Result:
Even though this lock API appears to be deprecated, we'll correct the
usage anyway. The non-deprecated NIOLock class doesn't have this
problem.
### Motivation:
In reviewing a copy of this file in swift-log, @czechboy0 noticed that
the call to `pthread_mutexattr_destroy` is missing. Since
pthread_mutexattr_t is like allocated on the stack rather than heap on
most platforms, this is likely not a memory leak. But for correctness
the missing destroy call should be added.
This change is the start of a resolution
[requested](https://github.com/apple/swift-log/pull/398#discussion_r2689459360)
in a corresponding Lock rollout in swift-log
### Modifications:
- Added missing call to `pthread_mutexattr_destroy`
- Duplicated test for `NIOLock` to also test `Lock`, as a sanity test.
### Result:
The new sanity test passes. If there are other ways this change can be
realistically verified as safe and proper, please feel free to provide
feedback in the PR.
Xcode-latest currently points to the 26.1 release so it gives us a false
sense of version coverage, and should be ignored.
### Motivation:
We do not need to build twice with the same environment.
### Modifications:
Set default value for Xcode latest beta enabled to `false`
### Result:
One fewer job generated for the macOS build matrix.
Co-authored-by: Rick Newton-Rogers <rnro@apple.com>
`NIOTypedHTTPClientUpgradeHandler.handlerAdded` will write upgrade
request if the channel is already active
### Motivation:
This has been added to make it easier to implement a websocket client
that supports proxies. If the upgrade handler is added after the proxy
connect has been processed previously nothing would happen.
### Modifications:
- Added new function
`NIOTypedHTTPClientUpgradeHandler.writeUpgradeRequest()` function. Call
this from `channelActive` and also from `handlerAdded` if the channel is
already active.
- Added test `testUpgradeHappensAfterHandlerAdded`
### Result:
NIOTypedHTTPClientUpgradeHandler now also works if it is added to a
channel after the channel is active
---------
Co-authored-by: Cory Benfield <lukasa@apple.com>
This re-enables documentation lost during refactoring work, under the
target _NIOFileSystem
resolves#3474
### Motivation:
During the refactoring of NIOFileSystem and recent Swift updates, the
mechanism to "shadow" symbols using `@_exported import` has stopped
working for documentation and imports for symbols, which means that
_NIOFileSystem is the target that needs to host the documentation for
this (for now)
### Modifications:
Moves DocC catalog into _NIOFileSystem target, and updates
disambiguation hashes on overloaded symbols in order to verify no
warnings are presented while generating documentation.
Updates .spi.yml to present _NIOFileSystem instead of NIOFileSystem
### Result:
Previous documentation should be available again, although at a slightly
different URI structure within Swift Package Index.
Co-authored-by: Cory Benfield <lukasa@apple.com>
Instead of evaluating inputs directly in the run step, save them to an
environment variable and evaluate that.
### Motivation:
Evaluating workflow inputs directly can lead to injection attacks, such
as those described at https://docs.zizmor.sh/audits/#template-injection
### Modifications:
Evaluate workflow inputs as environment variables so that they do not
inadvertently execute arbitrary shell injections.
### Result:
The workflows should be more secure against malicious inputs.
Add homeDirectory accessor to FileSystem
### Motivation:
Addresses #3381 by adding a `homeDirectory` property to FileSystem,
equivalent to `FileManager.default.homeDirectoryForCurrentUser`.
### Modifications:
- Added `homeDirectory` property to `FileSystemProtocol` and implemented
in `FileSystem`
- Implementation checks `HOME` environment variable first, falls back to
`USERPROFILE` on Windows, or uses `getpwuid_r(3)` on POSIX systems
- Added system call wrappers (`system_getuid`, `libc_getpwuid_r`) with
proper platform guards
- Added `FileSystemError.getpwuid_r()` error helper
### Result:
Users can now access the home directory via `FileSystem.homeDirectory`,
returning a `FilePath` asynchronously. Follows the same pattern as
`currentWorkingDirectory` and `temporaryDirectory`.
Co-authored-by: Cory Benfield <lukasa@apple.com>
### Motivation:
The documentation for String(buffer:) initializer does not clearly
indicate
that this operation will always succeed, which may leave developers
uncertain
about error handling requirements.
fixes: https://github.com/apple/swift-nio/issues/3449
### Modifications:
Updated the documentation for String(buffer:) to explicitly mention that
the initialization will always succeed.
### Result:
Developers will have clearer understanding that String(buffer:) is a
safe
operation that does not require error handling.
Signed-off-by: Karan <karanlokchandani@protonmail.com>
### Motivation:
Currently, pending consumer closures remain in the
`{in}{out}boundBufferConsumer` queues of `EmbeddedChannelCore` even
after the channel closes. It is also possible to enqueue consumers
*after* the channel closes. In these cases, the consumer closures will
never be invoked and this can lead to unfavourable behaviour, as
observed in `NIOAsyncTestingChannel`'s `waitFor{In}{Out}boundWrite`
methods (the only places these queues are currently used).
`NIOAsyncTestingChannel`'s `waitFor{In}{Out}boundWrite` methods complete
a continuation *inside* the consumer closure. In the cases described
above, the continuation never completes and therefore
`waitFor{In}{Out}boundWrite` never returns.
### Modifications:
- Updated the element type in `EmbeddedChannelCore`'s
`{in}{out}boundBufferConsumer` from `(NIOAny) -> Void` to
`(Result<NIOAny, Error>) -> Void`.
- This is so that the `.failure` case can be used to notify the consumer
closure that the channel has closed.
- Changed the visibility of the `{in}{out}boundBufferConsumer`
properties from `internal` to `private` in order to prevent the queues
from being accessed and being appended to without the call site
considering whether the channel has been closed.
- Added new `internal` methods named
`enqueue{In}{Out}boundBufferConsumer(_:)` which take the consumer
closure as an argument and only append to the corresponding queue if the
channel isn't closed.
- If the channel is closed, the consumer closure is invoked immediately
with `.failure(ChannelError.ioOnClosedChannel)`.
- Updated `EmbeddedChannelCore`'s `close0` method to return a
`.failure(ChannelError.ioOnClosedChannel)` result to each closure in
`{in}{out}boundBufferConsumer` and empty both buffers.
- Updated `NIOAsyncTestingChannel`'s `waitFor{In}{Out}boundWrite` to
throw an error in the continuation upon receiving a `.failure` result.
- Added associated test cases.
### Result:
`EmbeddedChannelCore`'s `{in}{out}boundBufferConsumer` queues can be
used more safely: all pending closures will be invoked upon channel
close. As a result, `NIOAsyncTestingChannel`'s
`waitFor{In}{Out}boundWrite` no longer indefinitely blocks when the
channel closes.
Fix coreCount on Linux when using cgroup v2 with CFS throttling disabled
### Motivation:
When using `swift-nio` on Linux with cgroup v2 enabled, but with CFS
throttling disabled, it falls back to attempting to read the cpuset file
at the cgroup v1 path. This does not exist, which in turns falls back to
returning `_SC_NPROCESSORS_ONLN`, which will return the total number of
cores available (ignoring cgroup assignments).
This has unexpected effects, including the default behaviour of starting
the `MultiThreadedEventLoopGroup.singleton` with significantly more
event loops than cores available to the workload.
### Modifications:
- Adds `SystemCalls.statfs`, and associated constants, to determine the
cgroup version.
- Adds `Linux.cgroupVersion()` API to expose cgroup version.
- Adds `Linux.cgroupV2MountPoint` variable to determine the cgroup v2
mount point.
- Adds `Linux.cpuSetPathV1` & `Linux.cpuSetPathV2` (and
`Linux.cpuSetPath` convenience) variables to determine the correct cpu
set path.
- Alters `System.coreCount` to use the appropriate logic from above to
ensure that `cpuset.cpus` is parsed from the correct location.
### Result:
`Linux.coreCount` should correctly parse and return the core count on
Linux cgroup v2 enabled systems (when CFS throttling is disabled), while
maintaining correctness for other configurations.
---------
Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
Co-authored-by: Cory Benfield <lukasa@apple.com>
Limit Darwin Job execution to apple org.
### Motivation:
When the repo is forked, the forks do not have access to the self-hosted
CI, so it should not block actions in the forked environment.
### Modifications:
Conditionalize Darwin job execution.
### Result:
macOS CI will not queue on forks.
### Motivation:
From
https://github.com/apple/swift-nio/actions/runs/20197120190/job/57982705638
onwards, the Integration Test benchmark runs have been failing for
`Linux (nightly-main)` due to allocations for seven tests falling below
the defined thresholds.
### Modifications:
Updated thresholds for the tests where the number of allocations were
out-of-threshold (seven in total).
### Result:
The Integration Test run for `Linux (nightly-main)` no longer fails.
Extract macOS benchmarks into a separate reusable workflow to completely
remove them if they are not meant to be used.
### Motivation:
macOS Benchmarks is an opt-in workflow. If no macOS versions selected to
run benchmarks on, there is now a skipped matrix jobs, creating
unnecessary visual and cognitive noise during workflow results analysis:
<img width="391" height="369" alt="Screenshot 2025-12-10 at 14 22 50"
src="https://github.com/user-attachments/assets/959ff2a1-3872-4bff-97ac-1dca6d2d4ea5"
/>
### Modifications:
macOS benchmarks workflow is extracted into a separate reusable
workflow.
### Result:
- If a repo is not running macOS benchmarks, there is no extra skipped
jobs.
- When willing to run macOS benchmarks, `macos_benchmarks.yml` workflow
should be used.
- This is a breaking change in the reusable workflows interface, so all
the repos (just the `swift-log`?) need to adopt the new reusable
workflow.
Test runs:
- old workflow run with [unused macOS benchmarks skipped and
visible](https://github.com/apple/swift-nio/actions/runs/20102000384/job/57675171794)
- new workflow run with [no macOS benchmarks
visible](https://github.com/apple/swift-nio/actions/runs/20102837431)
because they are not used
- new workflow run with actually [executed and visible macOS
benchmarks](https://github.com/apple/swift-nio/actions/runs/20103726421)
Add ByteBuffer.readableBytesUInt8Span
### Motivation:
Provide access to readableBytes as a Span<UInt8>
### Modifications:
Added computed property `ByteBuffer.readableBytesUInt8Span`. I also
attempted to add `ByteBuffer.mutableReadableBytesUInt8Span` but due to
an apparently faulty exclusivity issue I couldn't get this to work. See
https://github.com/swiftlang/swift/issues/81218.
### Result:
You can access the readable bytes of a ByteBuffer as a Span<UInt8>
Motivation:
The various 'withMumbleContinuation' APIs are supposed to be invoked
synchronously with the caller. This assumption allows a lock to be
acquired before the call and released from the body of the
'withMumbleContinuation' after e.g. storing the continuation. However
this isn't the case and the job may be re-enqueued on the executor
meaning that this is pattern is vulnerable to deadlocks.
Modifications:
- Drop and reacquire the lock in TokenBucket.
- Switch to NIOLockedValueBox
Result:
Lower chance of deadlock
Motivation:
I'm unhappy with AddressedEnvelope.Metadata, and I plan to change it.
Before I change it, I want some way to get a clear picture of whether my
changes make things better or worse.
Modifications:
Added a bunch of benchmarks
Result:
Some data will be available.
---------
Co-authored-by: George Barnett <gbarnett@apple.com>
Added extra documentation to `channel.remoteAddress` field to capture a
scenario where this field might be `nil`
### Motivation:
It is somewhat common for users to have code like
`channel.remoteAddress!` in their implementation, as it is a reasonable
assumption to think a socket connection will have an associated remote
address. However, in at least one known situation this might not be the
case. When that happens, user's code might crash due to the force unwrap
of the optional field.
### Modifications:
Introduced more documentation to make it clear that users should be
prepared to handle the `nil` scenario.
### Result:
Less frequent mishandling of `channel.remoteAddress`.
### Motivation:
Additional partial platform support.
### Modifications:
* Create a new CNIOBSD module for OpenBSD, for general cleanliness, and
make use of it throughout. Some of the changes are borrowed directly
from CNIOLinux; some may technically be unnecessary; I am erring
somewhat on expediency to functionality.
* Since `malloc_size` is unavailable on OpenBSD, and some of the helpers
make use of ManagedBufferPointer which makes use of it, mark some of
this as unavailable as well.
* Usual pthread optional typing changes, since pthread types are
pointers on this platform.
* Add conditionals to exclude other functionality not available here,
like IP_RECVPKTINFO or IP_PKTINFO.
* d_ino is a backwards-compatibility macro valued token for dirent, so
instead, just expand with a conditional.
* Use kqueue on OpenBSD. This necessitates adding some conditionals for
type and feature compatibility.
* The vsock API is unavailable on OpenBSD.
### Result:
Tested the NIOTCPEchoClient and NIOTCPEchoServer appears to work and
that swift-nio-ssh (hopefully wlog) builds with a local repository with
these changes.
Because NIOFS/_NIOFileSystem depend on some non-portable components,
such as extended attributes, sendfile, non-portable linkat flags, and
renameat2, this is only just partial OpenBSD support, which means that
`swift build` on the full swift-nio project won't build cleanly, but at
least the portable parts can be used to build servers and clients. This
commit will mark the linked bug as fixed; I will open a new bug for file
system support.
Fixes#3383.
---------
Co-authored-by: Rick Newton-Rogers <rnro@apple.com>
Motivation:
The various 'withMumbleContinuation' APIs are supposed to be invoked
synchronously with the caller. This assumption allows a lock to be
acquired before the call and released from the body of the
'withMumbleContinuation' after e.g. storing the continuation. However
this isn't the case and the job may be re-enqueued on the executor
meaning that this is pattern is vulnerable to deadlocks.
Modifications:
- Drop and reacquire the lock in the NIOThrowingAsyncSequenceProducer.
- Merge 'next()' and 'next(for:)' methods in the state machine into a
single func; this reduces the amount of duplicated logic across the two
functions.
Result:
Lower chance of deadlock
Motivation:
This is a follow up to 5bf841dd to handle the yield task being cancelled
between dropping the lock and re-acquiring it a moment later in the
'withContinuation' block.
Modifications:
- Add an extra cancellation check when yielding with a continuation.
Result:
Fewer issues
Motivation:
The various 'withMumbleContinuation' APIs are supposed to be invoked
synchronously with the caller. This assumption allows a lock to be
acquired before the call and released from the body of the
'withMumbleContinuation' after e.g. storing the continuation. However
this isn't the case and the job may be re-enqueued on the executor
meaning that this is pattern is vulnerable to deadlocks.
Modifications:
- Drop and reacquire the lock in the NIOAsyncWriter
Result:
Lower chance of deadlock
### Motivation:
Unfortunately, even if no metics delegate has been configured,
significant work is being done _each EL tick_. Concretely:
- 2 `NIODealine.now()` calls which are expensive particularly on some
hypervisors (may cause a VMEXIT!)
- Some unnecessary calculations
### Modifications:
- Only perform the metrics delegate work if a delegate has actually been
set
### Result:
If no delegate is set, each EL tick will now be faster.
Co-authored-by: George Barnett <gbarnett@apple.com>
Motivation:
TCPEcho has some run-to-run variation which makes CI flaky.
Modifications:
- Add a little slack to TCPEcho; it has a low total alloc count so some
slack is fine as it's less than a per iteration allocation
Result:
CI less flaky