Motivation:
There are use-cases for SwiftNIO where there are no actual sockets but
rather two pipe file descriptors - one for input, one for output.
There's no real reason why SwiftNIO shouldn't work for those.
Modifications:
Add a PipeChannel.
Result:
More use-cases for SwiftNIO.
Motivation:
The WebSocketFrameEncoder naively allocated a new block to write the
frame header into every time it wrote. This is excessive: in many cases
it would be able to re-use the same buffer as last time.
Modifications:
- Attempt to re-use the buffer we used for the last header.
Result:
Fewer allocations in some applications.
Motivation:
A dark force walks abroad our lands. In a place where well-behaved
processes close their blinds, lock their doors, and try not to make
noise late at night, processes that shine just a little too brightly,
consume just a little too much RAM, attract the attention of a dark
force whose name is spoken only in whispers. Some call this force a
myth, but others say that the deniers of this force have whispered dark
incantations, invoking the power word "oom_adj".
It is time we intervened to keep the law-abiding processes in our CI
systems safe.
Modifications:
- Prevent the websocket performance tests comnsuming 4GB of RAM.
Result:
Peace will reign.
Motivation:
To improve the performance of a given component it is very helpful to
know how it performs! This patch adds benchmarks and allocation counter
tests to NIO for websocket frame encoding.
Modifications:
- Wrote some benchmarks for WebSocket frame encoding.
- Wrote some allocation counter tests for WebSocket frame encoding.
- Extend the allocation counter tests to properly account for sub-tests
Result:
Better insight
Motivation:
Cory recently mentioned that
> handlerAdded is generally a better choice for a "setup" function than
> channelRegistered, as a handler is always guaranteed to receive
> handlerAdded, but is not guaranteed to receive channelRegistered
> (depending on specifics of pipeline setup).
Thus using the better way in examples is good.
Modifications:
- change `channelRegistered` to `handlerAdded`
Result:
- More idiomatic example app
* NIOHTTP1TestServer implementation
* Test simple request and two concurrent requests
* Accepting multiple connections but keeping only one active at a time
* Linux tests
* Addressed some PR comments
motivation: calling syncShutdownGracefully on the event loop can lead to deadlock
changes: assert before calling syncShutdownGracefully that no eventloop context exists
motivation: support swift 5.1 release
changes:
* update docker file to use official docker images
* update swift 5.0 and swift 5.1 docker-compose setup to use the official docker images
Motivation:
The integration tests depended on python in order to print 80,000 x
characters.
Modifications:
Remove the python dependency and express the same with `dd` & `tr`.
Result:
Fewer dependencies.
Motivation:
BaseSocketChannel's description method accessed the (mutable) socket
property of the channel which must only be accessed on the EventLoop.
Description however call be called on any thread.
Modifications:
Don't access the socket from description.
Result:
- more thread-safety
- fixes#1141
Motivation:
I ran across a case in a test where `HTTPResponseStatus(statusCode: 418)`
unexpectedly returned a `.custom` response status.
Modifications:
- Add a missing `case` for creating a status from `418`
- Shuffled some of cases around so that they are correctly listed in the
correct 2xx, 3xx, 4xx etc. sections
Result:
- `HTTPResponseStatus(statusCode: 418)` now returns `.imATeapot`
Motivation:
Now that Xcode 11 has GM'd, we should recommend the best workflow which
very clearly is Xcode 11's new package support.
Modifications:
Edit README to explain how to use Xcode's package support.
Result:
Happier users.
Motivation:
When dealing with `Result` types and promises it is inconvenient having to
switch over the result in order to succeed or fail a promise.
Modifications:
- Allow promises to be completed with a `Result<Value, Error>` directly.
- Added tests.
Result:
Promises are easier to fulfill with `Result` types.
Motivation:
Previously the maths on NIODeadline/TimeAmount could sometimes crash and
weren't always right.
Modifications:
Fix the maths and add tests.
Result:
Fewer crashes, more happy times.
Motivation:
NIO's Lock currently just deadlocks if a thread which already holds a
lock tries to reacquire it. This however isn't even really defined
behaviour.
Modifications:
Switch us to a guaranteed crash from a unguarnateed hang.
Result:
Easier to debug deadlocks with NIO's lock.
Motivation:
Documentation in jazzy looks misleading, listing all methods under
"cascade" since no new MARKs are defined
Modifications:
declare more MARKs, it's repetetive but not wrong now
Result:
Nicer docs
Motivation:
In the grpc-swift test suite, we saw a case where the server would
always immediately close the accepted socket. This lead NIO to misbehave
badly because kqueue would send us the `readEOF` before the `writable`
event that finishes an asynchronous `connect`.
What happened is that we just dropped the `readEOF` on the floor so we
would never actually tell the user if the channel ever went away.
Modifications:
Only register for `readEOF` after becoming active.
Result:
- we're happy with servers that immediately close the socket
Motivation:
@ravikandhadai suggested some minor changes in #1117 which we should
apply.
Modifications:
Apply all suggested changes all over the code base.
Result:
- fixes#1117
The inclusion of `cpp_magic.h` in `CNIOAtomics.h` is unnecessary and pollutes the namespace of anyone else importing the header. NIO now also requires Swift 5, which itself will not be built with a Clang too old to understand `_Nonnull`. Note: Removing the extra import of cpp-magic.h required moving it to the src/ directory to avoid complaints about its inclusion (or lack thereof) in the module's umbrella header.
Motivation:
Everything should compile on as many platforms as possible.
Modifications:
Guard FileManager.temporaryDirectory behind
`#available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, macCatalyst 13, *)`
instead of just macOS 10.12.
Result:
Tests should build on iOS and friends too.
Motivation:
With multiple MultiThreadedEventLoopGroups, the thread names are often
useless because there can be two NIO-ELT-#0s etc.
Modifications:
Add a unique MultiThreadedEventLoopGroup identifier.
Result:
NIO thread names unique. Side benefit: It should be easier to see if
people cycle through MTELGs like crazy.
Motivation:
Although that's a rare usecase, the Bootstraps must support random
EventLoops. That includes the EventLoops they're called on but also the
EventLoops of the futures returned from the channel initializers.
Modifications:
Make sure we're always on the correct EventLoop.
Result:
Fewer crashes and bugs.
The `atomic_flag` wrappers (structure, `create` helper, and `destroy` helper) are not referenced from anywhere else in the NIO source tree; they can not be invoked, and appear to serve no purpose. Under sufficiently strict compiler settings, they even cause errors due to the functions lacking prototype declarations.
Motivation:
Making CircularBuffer conform to ExpressibleByArrayLiteral enables
directly initializing it from an array literal, which can sometimes
make its use simpler and more natural, for instance:
foo.circularBuffer = [1,2,3] // vs `= CircularBuffer([1,2,3])`
Foo(circularBuffer: [a, b, c]) // vs `: CircularBuffer([a, b, c])`
This is consistent with other standard Swift collections, such as
Set, as well as existing NIO types (eg: WebSocketMaskingKey).
Modifications:
Extend CircularBuffer to conform to ExpressibleByArrayLiteral
Result:
CircularBuffer can now be initialized from array literals
Motivation:
EmbeddedChannel used to only support IOData on its outbound path, that
has been fixed in #763.
Modifications:
Remove the incorrectly documented brokenness.
Result:
More correct docs.
Motivation:
In general, Swift collections and sequences automatically conforms to
Equatable and Hashable when their Element conforms to Equatable and
Hashhable, respectively. This wasn't the case of CircularBuffer, which
was unintuitive and could cause useless boilerplate code.
Modifications:
CircularBuffer has been extended so that it conforms to Equatable when
its Element is Equatable, and to Hashable when its element is Hashable.
Corresponding test cases have been added.
Result:
Appropriate conditional conformances of CircularBuffer to Equatable and
Hashable
Motivation:
NIOThreadPool was grossly abusing Dispatch to block a large number of
threads for (usually) blocking IO work.
Modifications:
Back the NIOThreadPool by NIOThreads (pthreads) instead of
DispatchQueues.
Result:
Less abuse.
Motivation:
In #1091 we fixed the most common case of handlerRemoved being called
multiple times. There was still another (less likely) problem left which
is if a manual removal is triggered from _within_ the handlerRemoved
call from a pipeline teardown, then we would still call handlerRemoved
another time.
Modifications:
Properly guard against handlerRemoved being called twice.
Result:
Fewer bugs.
Motivation:
Despite the fact that we already stopped delivering unsolicited
responses for the HTTP response decoder, there was a window where we
would deliver a second .head for a response that come without a request.
Modifications:
Don't deliver a second .head even if send together with a first, legit
response.
Result:
Being a HTTP client using NIO is now easier.
Motivation:
There is currently a pair of windows in which it is possible for the
HTTPServerUpgradeHandler to buffer some data without replaying it. This
can happen if it is reentrantly called just after it finishes
unbuffering data, which is not great.
To avoid this, we move to execute this data delivery while we're
removing ourselves. This ensures that we are confident that we cannot be
reentrantly called after our last outcall, meaning we can be confident
of 100% data delivery.
Modifications:
- Moved delayed data delivery to removeHandler.
Result:
Less chance of quiet data loss
* fix double remove of handlers
Motivation:
Previously, it was possible that a handler was removed twice: Once by
Channel teardown and another time by a user-trigger removal that wasn't
instantaneous. This racy situation can happen in the real world. NIO
behaved wrongly in two ways:
1. we would call `handlerRemoved` twiced
2. ByteToMessageHandler would fail an assertion about the current
removal state
Modifications:
- Only call `handlerRemoved` when the handler actually gets removed.
- Fix the assertion.
Result:
fewer bugs
* Update Sources/NIO/ChannelPipeline.swift
Co-Authored-By: Cory Benfield <lukasa@apple.com>
Motivation:
Without niling out it may linger around once the last test has
completed, and keep some messages in memory which will not be inspected
anymore
Modifications:
nil out the writeRecorder same as all other fields are currently nilled
out
Result:
In case XCTest keeps the class around, not keeping around the messages
stored by the writeRecorder
* Fix hanging thread when shutting down an already closed EventLoopGroup
* Generate Linux tests
* Remove accidental shutdownLock.unlock
* Move dispatching of callbacks out of lock
* Use Lock.withLock instead of manual lock/unlock
* Remove superfluous lock.unlock
Motivation:
To give visibility to recently added examples.
To satisfy issue #465
Modifications:
Added links to examples in readme.
Slightly re-arranged the order so that echo examples are next to each other in the list.
Result:
You can now see the UDP, HTTP and WebSocket client examples from the README file.