Closed hjuraev closed 4 years ago
Can you give a bit more information on what you ran, and steps to reproduce? The stack trace is not symbolicated so it's hard to tell what's happening.
@kylebrowning it's a leak of this promise. In debug mode, NIO will print the file/line where the leaking promise was allocated:
Fatal error: leaking promise created at (file: "/.build/checkouts/apnswift/Sources/APNSwift/APNSwiftConnection.swift", line: 197): file /.build/checkouts/apnswift/Sources/APNSwift/APNSwiftConnection.swift, line 197
I can see a very straightforward leak there. If stream
is already closed by the time you call writeAndFlush
, it will fail (because the channel is already deallocated) so the promise will be leaked.
In case the writeAndFlush
fails, you'll need to also fail responsePromise
with the error you get.
@weissi is there a way I can make it leak?
return stream.writeAndFlush(context).recover { error in
responsePromise.fail(error)
}
@kylebrowning Couple of options:
ChannelOutboundHandler
to the stream channel pipeline that just fails all writesrecover
is not a great idea btw, that makes the error go away. You want
return stream.writeAndFlush(context).flatMapErrorThrowing { error in
responsePromise.fail(error)
throw error
}
I'm having this same issue with version 1.7.0.
I got an error on push: ioOnClosedChannel Fatal error: leaking promise created at (file: "..../APNSwift/Sources/APNSwift/APNSwiftConnection.swift", line: 197): file ..../APNSwift/APNSwiftConnection.swift, line 197 2019-12-23 09:47:21.808779-0800 Run[57121:1075060] Fatal error: leaking promise created at (file: "..../APNSwift/APNSwiftConnection.swift", line: 197): file ...APNSwift/APNSwiftConnection.swift, line 197
@grosch just to be sure, mind attaching a backtrace? Here how you can do this from Xcode or lldb: https://gist.github.com/weissi/49bcd588ecc394e29afa2badb3278c73
@kylebrowning This is how I'm calling it:
let payload = "{}".data(using: .utf8)!
var rawBytes = ByteBufferAllocator().buffer(capacity: payload.count)
rawBytes.writeBytes(payload)
return req.apns.send(rawBytes: rawBytes, pushType: .background, to: reg.device.pushToken, topic: reg.pass.type)
.flatMapError {
// Unless APNs said it was a bad device token, just ignore the error.
guard case let APNSwiftError.ResponseError.badRequest(response) = $0, response == .badDeviceToken else {
return req.eventLoop.future()
}
// Be sure the device deletes before th e registration is deleted.
// If you let them run in parallel issues might arise depending on
// the hooks people have set for when a registration deletes, as it
// might try to delete the same device again.
return reg.device.delete(on: req.db)
.flatMapError { _ in req.eventLoop.future() }
.flatMap { reg.delete(on: req.db) }
}
Thanks @grosch ! @kylebrowning this is the relevant bit
* thread #6, name = 'NIO-ELT-0-#4', stop reason = Fatal error: leaking promise created at (file: "/Users/scott/Library/Developer/Xcode/DerivedData/server-empyslfnoeqomsdexfdameshsaij/SourcePackages/checkouts/APNSwift/Sources/APNSwift/APNSwiftConnection.swift", line: 197)
frame #0: 0x00007fff71cdada0 libswiftCore.dylib`_swift_runtime_on_report
frame #1: 0x00007fff71d522a3 libswiftCore.dylib`_swift_stdlib_reportFatalErrorInFile + 211
frame #2: 0x00007fff71c68ade libswiftCore.dylib`function signature specialization <Arg[0] = Exploded, Arg[1] = Exploded, Arg[2] = Exploded> of closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 238
frame #3: 0x00007fff71c68c57 libswiftCore.dylib`function signature specialization <Arg[0] = Exploded, Arg[1] = Exploded, Arg[2] = Exploded> of closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 87
frame #4: 0x00007fff71a3989c libswiftCore.dylib`function signature specialization <Arg[1] = [Closure Propagated : closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never, Argument Types : [Swift.StaticStringSwift.UnsafeBufferPointer<Swift.UInt8>Swift.UIntSwift.UInt32]> of generic specialization <()> of Swift.String.withUTF8<A>((Swift.UnsafeBufferPointer<Swift.UInt8>) throws -> A) throws -> A + 236
frame #5: 0x00007fff71c3a3e0 libswiftCore.dylib`function signature specialization <Arg[0] = Exploded, Arg[1] = Exploded> of Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 496
frame #6: 0x00007fff71a38e59 libswiftCore.dylib`Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 25
* frame #7: 0x00000001001386eb Run`closure #1 in EventLoopFuture.deinit(self=0x00000001025a0990) at EventLoopFuture.swift:418:21
frame #8: 0x00000001001ea28e Run`closure #1 in implicit closure #1 in debugOnly(body=0x000000010013f040 Run`partial apply forwarder for closure #1 () -> () in NIO.EventLoopFuture.deinit at <compiler-generated>) at Utilities.swift:24:14
frame #9: 0x00000001001ea208 Run`debugOnly(body=0x000000010013f040 Run`partial apply forwarder for closure #1 () -> () in NIO.EventLoopFuture.deinit at <compiler-generated>) at Utilities.swift:24:5
frame #10: 0x00000001001380e6 Run`EventLoopFuture.deinit(self=0x00000001025a0990) at EventLoopFuture.swift:414:9
frame #11: 0x0000000100138927 Run`EventLoopFuture.__deallocating_deinit(self=0x00000001025a0990) at EventLoopFuture.swift:0
frame #12: 0x00007fff71cdcaf0 libswiftCore.dylib`_swift_release_dealloc + 16
frame #13: 0x0000000100968bef Run`___lldb_unnamed_symbol1628$$Run + 47
frame #14: 0x00007fff71cdcaf0 libswiftCore.dylib`_swift_release_dealloc + 16
frame #15: 0x0000000100968d05 Run`___lldb_unnamed_symbol1629$$Run + 21
frame #16: 0x00007fff71cdcaf0 libswiftCore.dylib`_swift_release_dealloc + 16
frame #17: 0x000000010013f07a Run`___lldb_unnamed_symbol428$$Run + 42
frame #18: 0x00007fff71cdcaf0 libswiftCore.dylib`_swift_release_dealloc + 16
frame #19: 0x000000010013402b Run`outlined consume of Swift.Optional<@escaping @callee_guaranteed () -> (@owned NIO.CallbackList)> + 27
frame #20: 0x0000000100136395 Run`EventLoopPromise._resolve(value=failure, self=NIO.EventLoopPromise<NIO.Channel & AnyObject> @ 0x000070000b2fddd0) at EventLoopFuture.swift:227:9
frame #21: 0x0000000100136644 Run`EventLoopPromise.fail(error=ioOnClosedChannel, self=NIO.EventLoopPromise<NIO.Channel & AnyObject> @ 0x000070000b2fde78) at EventLoopFuture.swift:180:14
frame #22: 0x000000010078126d Run`closure #3 in HTTP2StreamChannel.configure(error=ioOnClosedChannel, self=0x000000010259f740, promise=some) at HTTP2StreamChannel.swift:178:22
frame #23: 0x000000010013c7ff Run`closure #1 in EventLoopFuture.whenFailure(self=0x00000001025a1dc0, callback=0x00000001007812d0 Run`partial apply forwarder for closure #3 (Swift.Error) -> () in NIOHTTP2.HTTP2StreamChannel.configure(initializer: Swift.Optional<(NIO.Channel, NIOHTTP2.HTTP2StreamID) -> NIO.EventLoopFuture<()>>, userPromise: Swift.Optional<NIO.EventLoopPromise<NIO.Channel>>) -> () at <compiler-generated>) at EventLoopFuture.swift:720:17
frame #24: 0x00000001001397e8 Run`EventLoopFuture._addCallback(callback=0x000000010013f610 Run`partial apply forwarder for closure #1 () -> NIO.CallbackList in NIO.EventLoopFuture.whenFailure((Swift.Error) -> ()) -> () at <compiler-generated>, self=0x00000001025a1dc0) at EventLoopFuture.swift:663:16
frame #25: 0x0000000100139942 Run`EventLoopFuture._whenComplete(callback=0x000000010013f610 Run`partial apply forwarder for closure #1 () -> NIO.CallbackList in NIO.EventLoopFuture.whenFailure((Swift.Error) -> ()) -> () at <compiler-generated>, self=0x00000001025a1dc0) at EventLoopFuture.swift:670:18
frame #26: 0x000000010013c56a Run`EventLoopFuture.whenFailure(callback=0x00000001007812d0 Run`partial apply forwarder for closure #3 (Swift.Error) -> () in NIOHTTP2.HTTP2StreamChannel.configure(initializer: Swift.Optional<(NIO.Channel, NIOHTTP2.HTTP2StreamID) -> NIO.EventLoopFuture<()>>, userPromise: Swift.Optional<NIO.EventLoopPromise<NIO.Channel>>) -> () at <compiler-generated>, self=0x00000001025a1dc0) at EventLoopFuture.swift:718:14
frame #27: 0x000000010078067d
So as expected, we get an .ioOnClosedChannel
so the writeAndFlush
failed with that and then the promise never gets fulfilled.
I haven't forgotten about this, I just haven't been able to write a test for it yet. #80
This is fixed in #86
Crashing with promise leak message
Fatal error: leaking promise created at (file: "/.build/checkouts/apnswift/Sources/APNSwift/APNSwiftConnection.swift", line: 197): file /.build/checkouts/apnswift/Sources/APNSwift/APNSwiftConnection.swift, line 197
Platform:
Current stack trace: 0 libswiftCore.so 0x00007f625a8f7ec0 swift_reportError + 50 1 libswiftCore.so 0x00007f625a968f60 _swift_stdlib_reportFatalErrorInFile + 115 2 libswiftCore.so 0x00007f625a88cf0e + 3514126
3 libswiftCore.so 0x00007f625a88d087 + 3514503
4 libswiftCore.so 0x00007f625a68282d + 1374253
5 libswiftCore.so 0x00007f625a863e68 + 3346024
6 libswiftCore.so 0x00007f625a681bc9 + 1371081
7 Run 0x000056280b0632d0 + 6386384
8 Run 0x000056280b118efe + 7130878
9 Run 0x000056280b118e78 + 7130744
10 Run 0x000056280b062cc6 + 6384838
11 Run 0x000056280b063507 + 6386951
12 libswiftCore.so 0x00007f625a8f99ab + 3959211
13 Run 0x000056280ab7e52f + 1254703
14 libswiftCore.so 0x00007f625a8f99ab + 3959211
15 Run 0x000056280ab7e645 + 1254981
16 libswiftCore.so 0x00007f625a8f99ab + 3959211
17 Run 0x000056280b069c6a + 6413418
18 libswiftCore.so 0x00007f625a8f99ab + 3959211
19 Run 0x000056280b05ebbb + 6368187
20 Run 0x000056280b060f58 + 6377304
21 Run 0x000056280b061214 + 6378004
22 Run 0x000056280b2d285d + 8939613
23 Run 0x000056280b0673fe + 6403070
24 Run 0x000056280b0643cb + 6390731
25 Run 0x000056280b064525 + 6391077
26 Run 0x000056280b06716a + 6402410
27 Run 0x000056280b2d1c2f + 8936495
28 Run 0x000056280b2df478 + 8991864
29 Run 0x000056280b0522ac + 6316716
30 Run 0x000056280b05de61 + 6364769
31 Run 0x000056280b0522cc + 6316748
32 Run 0x000056280b052317 + 6316823
33 Run 0x000056280add491f + 3705119
34 Run 0x000056280b059be4 + 6347748
35 Run 0x000056280b04d412 + 6296594
36 Run 0x000056280b050efb + 6311675
37 Run 0x000056280b055515 + 6329621
38 Run 0x000056280b05d92a + 6363434
39 Run 0x000056280b055b4f + 6331215
40 Run 0x000056280b117231 + 7123505
41 Run 0x000056280b1176c1 + 7124673
42 Run 0x000056280b117789 + 7124873
43 libpthread.so.0 0x00007f625a31b6db + 30427
44 libc.so.6 0x00007f6257f08850 clone + 63
Illegal instruction (core dumped)