Commit Graph

808 Commits

Author SHA1 Message Date
Johannes Weiß ba470b7888
just set 127.0.0.1 as localhost's IPv4 address (#258)
Motivation:

Previously we tried to use `host` to determine localhost's IPv4 address.
That didn't work reliably in Docker and sometimes on macOS. Let's just
fix this to 127.0.0.1.

Modifications:

Hardcode localhost's IPv4 address as 127.0.0.1.

Result:

More stable test_16_tcp_client_ip
2018-03-30 17:47:54 +01:00
Johannes Weiß fee0b6199e
make allocation counter test fail on error in subshell (#262)
Motivation:

In shell, subshells don't inherit the shell flags (such as `set -eu`)
and therefore need to set them again. The allocation counter test uses a
subshell but forgot to `set -eu` in the subshell.

Modifications:

`set -eu` in the subshell for the allocation counter tests.

Result:

if there's an error building the test program the test now fails.
2018-03-30 16:01:33 +01:00
Johannes Weiß 17c511464d allow some cool down time after allocation measurements (#257)
Motivation:

We have code running on multiple threads and certain allocations/frees
happen for example after a promise has been fulfilled. We can't
deterministically wait for that so the only thing we can do is sleep a
little and wait...

Modifications:

Added a 100ms delay after an allocation counted test run.

Result:

Hopefully we don't see this again:

    ["total_allocations": 322051, "remaining_allocations": 24], ["total_allocations": 322051, "remaining_allocations": -24]

where the first test run had 24 allocations that weren't freed and the
second one on the other hand had 24 frees for allocations that "didn't
happen"...
2018-03-30 16:35:37 +02:00
Johannes Weiß 23744213e6 make Channel lifecycle statemachine explicit (#220)
Motivation:

We had a lot of problems with the Channel lifecycle statemachine as it
wasn't explicit, this fixes this. Additionally, it asserts a lot more.

Modifications:

- made Channel lifecycle statemachine explicit
- lots of asserts

Result:

- hopefully the state machine works better
- the asserts should guide our way to work on in corner cases as well
2018-03-29 19:50:07 +02:00
Johannes Weiß 68db2325df
add a simple leak detector (#255)
Motivation:

Memory leaks are rare in Swift but they can happen. If we run a
realistic workload and the number of `malloc`s and `free`s is very close
to 0, we can be fairly sure we didn't have any (too bad) leaks.
Therefore this adds a simple leaks detector.

Modifications:

Add a leak detector.

Result:

We should now detect leaks even if the total number of allocations
doesn't increase.
2018-03-29 18:43:49 +01:00
Johannes Weiß c84b19a399
add an allocation counting integration test (#252)
Motivation:

In Swift, it's really easy to accidentally add allocations yet the
number of allocations is really important for performance.
Therefore it's useful to have an integration test that counts the number
of allocations and compares them to a reference (and fails if the number
of allocations increases).

Modifications:

- add an allocation counter
- add a HTTP1 client/server example that is run with the allocation
  counter intrumentation

Result:

We should now be able to track the number of allocations.
2018-03-29 18:31:08 +01:00
Johannes Weiß 224120c175
bring back the deprecated NIOPriorityQueue module (#250)
Motivation:

We moved the priority queue implementation into the main `NIO` module
for performance reasons. I initially thought we didn't expose it to
external packages but we did (thanks @lukasa).

Modifications:

Bring back the `NIOPriorityQueue` module but deprecate it.

Result:

Speed & backwards compatibility :)
2018-03-28 17:06:05 +01:00
Norman Maurer 34e64a0820
Simplify ChannelHandlerContext (#247)
Motivation:

We can simplify the init method of ChannelHandlerContext and replace one let by a computed property.

Modifications:

Remove some if let statements that we not need and use computed property.

Result:

Simpler code and need one less variable per ChannelHandlerContext.
2018-03-28 14:15:01 +02:00
Norman Maurer b1f948a115
Set hints for getaddrinfo to restrict results (#221)
Motivation:

We only use our GetaddrinfoResolver for SocketChannels (TCP stream channels), so we should set some hints for getaddrinfo.

Modifications:

Set proto and socktype hints.

Result:

More correct usage of getaddrinfo. Fixes https://github.com/apple/swift-nio/issues/201.
2018-03-28 10:49:05 +02:00
Frank Kair dbe321424d Refactors generate_linux_tests script (#236)
Motivation:

generate_linux_tests.rb is written in a non idiomatic way.

Modifications:

I used Rubocop to refactor the code.
More info: https://github.com/bbatsov/rubocop

Result:

A more idiomatic Ruby script.
2018-03-27 11:36:45 -07:00
Johannes Weiß c9c3974276 bring PriorityQueue/Heap implementations inline (#245)
Motivation:

We triggered extra allocations for the generics on PriorityQueue/Heap.
They unfortunately can't be solved using `@_specialize` as the element
type is `ScheduledTask`.
Fortunately we never exposed those types externally so we can just
inline without breaking the public API.

Modifications:

Moved everything from the `NIOPriorityQueue` module into the `NIO`
module.

Result:

Less allocations, more happiness.
2018-03-27 19:04:33 +02:00
Norman Maurer f4036e2b0d Make use of lock.withLockVoid to simplify code (#242)
Motivation:

We should make use of lock.withLockVoid to simplify our code and make it more robust.

Modifications:

- Replace manual lock() / unlock() calls by withLockVoid(...)
- Mark lock.withLock* as @_inlineable to ensure we not get an allocation for the closure.

Result:

Code is cleaner and easier to understand.
2018-03-27 15:22:57 +01:00
Norman Maurer 5eb21324fc
Update EmbeddedChannel state before notify connect and close promise. (#241)
Motivation:

We need to update isActive before notify the promises of connect and close to correctly refect Channel.isActive in callbacks.

Modifications:

- Correctly update isActive before notify promises.
- Add unit test.

Result:

Correct Channel state in callbacks.
2018-03-27 15:18:23 +02:00
Norman Maurer 94edbad2be
Directly use the IOEvent to init a SelectorEvent when using KQueue (#238)
Motivation:

When using KQueue we directly can tell what IOEvent we want to use in SelectorEvent without and branching.

Modifications:

Add new init method to SelectorEvent that takes the IOEvent directly and use it when using KQueue

Result:

Less branching per event when using KQueue
2018-03-27 13:45:10 +02:00
Norman Maurer 774f298dca
Remove unnecessary promise allocation in Selector.closeGently(...) (#237)
Motivation:

We can remove a promise allocation in Selector.closeGently if there are still Channels registered and also simplify the code a bit.

Modifications:

Remove creation of promise and just use eventLoop.new*Future(...) when needed.

Result:

Less allocations and cleaner code.
2018-03-26 19:50:20 +02:00
Cory Benfield 0a23199d7d
Remove busywork left over from flush promises. (#234)
Motivation:

The Socket channels and PendingDatagramWritesManager had a bunch of
overhead left over from when they were handling flush promises. This was
only adding to code complexity and perf cost.

Modifications:

Removed the promise label in markPendingWritePoint.

Reworked the code to stop expecting write promises in
PendingDatagramWritesManager.

Result:

Smaller, faster code.
2018-03-26 17:07:56 +01:00
Norman Maurer cce02c9e40
Remove one pair of lock() / unlock() during EventLoop run. (#235)
Motivation:

We can remove one lock() / unlock() pair by saving the next ready task during loop execution.

Modifications:

Remvoe one lock() / unlock() pair.

Result:

Less locking during EventLoop run executions.
2018-03-26 16:42:39 +02:00
Norman Maurer 6cf8ca4398 Remove #available(OSX 10.12, *) check which is not needed anymore (#233)
Motivation:

At some point we needed to check for #available(OSX 10.12, *) which is not true anymore as we use our own Thread impl.

Modifications:

Remove #available(OSX 10.12, *) check

Result:

Remove incorrect and not needed check.
2018-03-26 14:23:14 +01:00
Norman Maurer c3fc78fe00 Take closeFuture into account when closing EventLoopGroup (#231)
Motiviation:

When the Selector is closed we also close the registered Channels and notify the future once all the close operations complete. The problem here is that while the close operation may be complete already there may still be events flowing through the ChannelPipeline. The only way to ensure this not happens anymore is to take the closeFuture into account of each Channel (as the closeFuture will only be notified once all is done for a Channel).

Modification:

- Also take the closeFuture into account per Channel
- Add test

Result:

Safer shutdown of EventLoopGroup.
2018-03-26 12:07:28 +01:00
Helge Heß be00f2ebb9 Typo: writte => written (#230)
Fixed typo
2018-03-24 12:58:36 +00:00
Tim a0b7f646fb Fixes build issue on 4.1 (#229)
Motivation:

Resolves #228

Modifications:

Remove type information in empty closure fixed build warning with compiler suggestion

Result:

No API changes, no issues building on 4.1!
2018-03-23 16:28:43 +00:00
Norman Maurer 1bcf85dd24 Correctly fail EventLoopFuture for unsupported operations on ServerSocketChannel (#226)
Motivation:

ServerSocketChannel should just fail the EventLoopFuture for unsupported operations and not crash.

Modifications:

- Correctly fail the EventLoopFuture for unsupported operations
- Add unit test.

Result:

No more crashes when users invoke unsupported operations.
2018-03-23 15:02:31 +00:00
Norman Maurer eb60e8978f
Dissallow access and removal of Head and Tail ChannelHandlers (#225)
Motivation:

The Head and Tail ChannelHandlers should not be accessible as these are implementation details of the ChannelPipeline and removal of these will even make the whole ChannelPipeline not work anymore.

Modifications:

- Make it impossible to access / removal the Head and Tail ChannelHandlers
- Exclude the Head and Tail ChannelHandler from the debug String
- Add unit tests.

Result:

More robust ChannelPipeline.
2018-03-23 15:02:16 +01:00
Gopal Sharma 61f03a7a53 Annotate global constants that refer to C functions with @convention(c) (#223)
Motivation:

This fixes https://github.com/apple/swift-nio/issues/206.

Also see: https://bugs.swift.org/browse/SR-7242.

Modifications:

Annotated global constants that refer to C functions with @convention(c), and added explcit types.

Results:

https://bugs.swift.org/browse/SR-7242 is worked around.
2018-03-23 09:37:51 +00:00
Norman Maurer 91d7058a36
Not retry calling close(...) when EINTR is reported. (#217)
Motivation:

Usually we retry the syscall when EINTR is reported. This is not safe in the case of close(...) as the file descriptor may already be closed. The problem arise if this was the case and we retry it and the file descriptor is already reused again. In this case we would close a wrong file descriptor.

See:
  - https://bugs.chromium.org/p/chromium/issues/detail?id=269623
  - https://lwn.net/Articles/576478/

Modifications:

Ignore EINTR on close(...) and just assume the FD was closed.

Result:

Not possible to close the wrong file descriptor when close(...) reports EINTR.
2018-03-22 18:16:00 +01:00
Tibor Bödecs 1f83a1d5cb Changed EventLoop{Future,Promise}<()> occurances to EventLoop{Future,Promise}<Void> (#211) (#219)
Motivation:

Fix inconsistency of <Void> and <()> occurances in the codebase.

Modifications:

Changed EventLoop{Future,Promise}<()> occurances to EventLoop{Future,Promise}<Void>

Result:

Consistent code style for EventLoopPromise and EventLoopFuture.
2018-03-22 17:36:10 +01:00
Norman Maurer 536298389f Remove unsafe assert on Linux (#218)
Motivation:

b8055f7467 added some code to guard against the case when a fd is deregistered while processing ready events. On Linux it also added an assert which tried to verify that the fd in question is not registered anymore via epoll. The problem here is that it may also be closed which will have epoll_ctl fail with EBADF

Modifications:

Remove assert and add test-case which would have triggered the assert.

Result:

No more assertion error on linux.
2018-03-22 13:56:00 +00:00
Johannes Weiß f58e8318fb
move BaseSocketChannel to its own file (#212)
Motivation:

{,Server,Datagram,Base}SocketChannel hold quite a bit of complexity and
also a many of lines of code. Yet they all shared the very same file
which isn't great.

Modifications:

- moved BaseSocketChannel into its own file
- made the methods that need overriding internal (from `fileprivate`)

Result:

SocketChannel.swift has a lot fewer lines of code.
2018-03-21 17:15:53 +00:00
Johannes Weiß 24fbb1ba1b channelActive needs to happen before channelRead (#204)
Motivation:

`readIfNeeded` was triggered straight after the channel was registered
but _before_ `channelActive` was called which is wrong.

Modifications:

Moved the calls to `readIfNeeded` into `becomeActive0` and removed them
everywhere else (except some error path).

Result:

handle ChannelHandler lifecycle more correctly.
2018-03-21 17:03:46 +00:00
Norman Maurer 3c8caab5b6
Add some docs to note on which message types a bootstrapped Channel will operate. (#207)
Motivation:

It's not clear to a user which inbound / outbound messages is expected for the different Channel implementations. This can result into wrong code and confused users.

Modifications:

Add some docs to explain which messages are supported / expected by the different Channels that can be bootstrapped.

Result:

More clear docs.
2018-03-21 15:44:32 +01:00
Norman Maurer b8055f7467
Guard against the case when a Selectable is deregistered during Selector.whenReady(...) processing. (#210)
Motivation:

It's possible someone deregistered a Selectable while Selector.whenReady(...) is processed and an even for the now deregistered Selectable is ready. In this case we crashed (due a force-unwrap) on linux.

Modifications:

- Skip the processing of the Selectable if deregistered (by replacing force-unwrap with an if let).
- Add unit test.

Result:

No more crashes caused by this on Linux
2018-03-21 15:32:15 +01:00
Tibor Bödecs 9a6f34fcc9 ChannelInvoker.newPromise should pass file and line to eventLoop.newPromise (#202) (#208)
Motivation:

Introduced some new parameters to fix #202

Modifications:

Created new parameters for the file and line newPromise method inside ChannelOutboundInvoker.

Result:

File and line numbers are now passed to the eventLoop object, all unit tests have been passed.
2018-03-21 11:15:12 +01:00
Norman Maurer 8bf013d7bd If connectSocket() completes directly we need to mark channel as active (#205)
Motivation:

If connectSocket() completes directly we failed to mark the Channel active by calling becomeActive0(...).

Modifications:

Correctly call becomeActive0(...)

Result:

Mark Channel active if connect succeed directly.
2018-03-21 10:12:24 +00:00
Johannes Weiß 88b91259f6 fix message for non-blocking connect errors (#203)
Motivation:

If a non-blocking connect failed, the error indicated that `getsockaddr`
failed which isn't true.

Modifications:

Adjusted the message.

Result:

Fewer lies.
2018-03-20 19:11:42 +01:00
Norman Maurer 17d5da5a2c
Return failed EventLoopFuture when getOption(...) / setOption(...) is called on a closed Channel (#198)
Motivation:

We should return a failed EventLoopFuture when getOption(...) / setOption(...) is called on a closed Channel as otherwise it may not be safe to modify the Channel ioptions after its closed.

Modifications:

- Add guards that check if the Channel is still open and if not fail the operation.
- Add testcase

Result:

Calling getOption(...) / setOption(...) on a closed Channel fails.
2018-03-20 17:38:24 +01:00
Cory Benfield fef728cab0
HappyEyeballs should tolerate uncancellable tasks. (#191)
Motivation:

The HappyEyeballs state machine incorrectly assumed that it would always
be able to cancel any scheduled task that would execute on the event loop
that the state machine itself was running on. This is not accurate: if
the scheduled task is scheduled to execute at roughly the same time as
another callback into the state machine then it may be uncancellable.

Modifications:

Allowed the three scheduled tasks (connect timeout, connect delay, and
resolver delay) to fire in completed.

Result:

No fatalErrors in window conditions under high load
2018-03-21 01:14:47 +09:00
Cory Benfield 4a23d33c97
Ensure we wait for the promise to succeed. (#200)
Motivation:

If we don't wait for the promise to succeed it may not be succeded
before we tear the loop down. This causes precondition failures.

Modifications:

We now always wait for the promise to succeed.

Result:

My tests will run.
2018-03-20 23:58:59 +09:00
Cory Benfield 28014b0358 Better docs for threading guarantees of futures (#197) 2018-03-20 15:30:48 +01:00
Norman Maurer c2a31f7a02 Ensure fireChannelActive(...) is always called before fireChannelRead(...) (#195)
Motivation:

fireChannelActive(...) must always be called before fireChannelRead(...) which was not the cause all of the times as once ChannelOptions were applied to the accepted SocketChannel it was possible that read0() was called during this. This would then lead to an assert error as it tried to reregister on the Selector before we ever registered.

Modifications:

- Ensure we only try to reregister once we have registered to the Selector
- Only trigger read0() or pauseRead0() if the autoRead value actually changed
- Add unit test

Result:

Correct order of events and no crashes.
2018-03-20 21:44:45 +09:00
Cory Benfield a3fad287c3 Add docs to explain inbound/outbound (#142) 2018-03-19 19:38:24 +01:00
Norman Maurer b6dbaa584e
Fix warnings in tests. (#193)
Motivation:

When running swift test two warnings were printed.

Modifications:

- Signal that we want to ignore the return value
- Use boolean test in the while loop

Result:

Cleaner build
2018-03-19 19:36:10 +01:00
Norman Maurer 58a9651d90
Re-use same ContiguousArray for tasks copy operations. (#192)
Motivation:

We allocated a new ContiguousArray per each EventLoop run when tasks needed to be executed. We can just re-use the same instance all the time and so safe malloc operations (we will need to do memset tho).
Beside this we also did not reserve the needed capacity up fron which could lead to realloc operations.

Modifications:

- Reuse same ContiguousArray instance
- Correctly set the initial capacity

Result:

Less overhead when processing tasks via the EventLoop
2018-03-19 19:35:43 +01:00
Cory Benfield 28d4ddb33b
Correctly expose backward-compat shim for header iterator. (#194)
Motivation:

header iterator that could be used to keep access to the iterator with
type erasure. However, it was accidentally made internal, and therefore
useless.

Modifications:

Made the shim public.

Result:

Users can actually upgrade their systems.
2018-03-19 23:53:20 +09:00
Bas Broek 1e7410aab8 Conform to the Swift bool naming guidelines
Motivation:

Changes the Boolean `fulfilled` to `isFulfilled` to make it more clear it is in fact a Boolean.

Also changes a `func isRecoverable()` to `var isRecoverable`.

Both of these were non-public, so this is no breaking change.

Modifications:

Renamed one Boolean and changed one function to a variable.

Result:

No use of unncessary (and potentially misinforming) functions, as well as adhering to the Swift boolean naming guidelines.
2018-03-19 14:55:53 +01:00
Bas Broek afa1037410 Prefer passing functions to flatMap
Motivation:

Passing in a function directly makes the code a bit more concise.

Modifications:

Changing `flatMap { Int($0) }` to `flatMap(Int.init)`.

Result:

More concise code.
2018-03-19 14:55:53 +01:00
Bas Broek ce4ccc519c Fix indentation 2018-03-19 14:55:53 +01:00
Bas Broek a095decbc2 Prefer if case over switch
Motivation:

There are quite a few `switch`es that cover just two cases. Explicitly state this via an `if case` + `else` structure.

Modifications:

Changes something like:

switch a {
case .b:
  return c
default:
  return d
}

to

if case .b = a {
  return c
} else {
  return d
}

Result:

This should prevent misinterpretation and thus potential bugs in the future.
2018-03-19 14:45:32 +01:00
Bas Broek 4c89a4e675 Give symbols some breathing room
Motivation:

Adds spacing around a `+` and `{`.
2018-03-19 14:44:08 +01:00
Bas Broek 1db0be8ed9 Infer return types
Motivation:

Removes unncessary explicit types that are inferred.

Modifications:

Infer types that are being returned from a function or computed variable.

Result:

Cleans up the code.
2018-03-19 14:43:55 +01:00
Bas Broek b180113d81 Improve switch readability
Motivation:
This changes two things:
- it removes the negation of non-used associated types (the removal of `(_)`).
- it prefers exhausting `switch`es over `default`ing.

This change does not impact bahavior; it is pure refactoring.

Modifications:

Omitting needless `(_)`'s and explicitly exhausting switches.

Result:

This change is pure refactoring.
2018-03-19 14:43:38 +01:00