Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crash in alpha 17 #949

Closed
AVVS opened this issue Aug 21, 2020 · 13 comments · Fixed by #950
Closed

crash in alpha 17 #949

AVVS opened this issue Aug 21, 2020 · 13 comments · Fixed by #950
Labels
kind/bug Feature doesn't work as expected.

Comments

@AVVS
Copy link

AVVS commented Aug 21, 2020

Describe the bug

Crash triggered by transition to idle state from keepalive handler
iOS 13.6.1 alpha 17

Not sure how to reproduce - had these reports in crashlytics, would be happy to debug further if you can guide me
on what I can do to provide more information

Thanks!

Crashed: NIO-ELT-2-#0
0  GRPC                           0x10841f890 ConnectionManager.idle() + 579 (ConnectionManager.swift:579)
1  GRPC                           0x10843e928 GRPCIdleHandler.idle(context:force:) + 112 (<compiler-generated>:112)
2  GRPC                           0x10843d990 GRPCIdleHandler.userInboundEventTriggered(context:event:) + 77 (GRPCIdleHandler.swift:77)
3  NIO                            0x108721574 ChannelHandlerContext.invokeUserInboundEventTriggered(_:) + 84 (<compiler-generated>:84)
4  NIO                            0x108719390 ChannelHandlerContext.fireUserInboundEventTriggered(_:) + 40 (<compiler-generated>:40)
5  GRPC                           0x108441e74 partial apply for closure #1 in _ChannelKeepaliveHandler.scheduleClose(timeout:context:) + 141 (GRPCKeepaliveHandlers.swift:141)
6  GRPC                           0x10841bf24 thunk for @escaping @callee_guaranteed () -> (@error @owned Error) + 20 (<compiler-generated>:20)
7  GRPC                           0x108441ebc partial apply for thunk for @escaping @callee_guaranteed () -> (@error @owned Error) + 16 (<compiler-generated>:16)
8  NIO                            0x10879b5ac closure #1 in SelectableEventLoop.scheduleTask<A>(deadline:_:) + 217 (SelectableEventLoop.swift:217)
9  NIO                            0x10879f304 partial apply for thunk for @escaping @callee_guaranteed () -> () + 20 (<compiler-generated>:20)
10 NIO                            0x10879e698 partial apply for thunk for @escaping @callee_guaranteed () -> (@out ()) + 20 (<compiler-generated>:20)
11 NIO                            0x10879e6c0 partial apply for closure #4 in SelectableEventLoop.run() + 28 (<compiler-generated>:28)
12 NIO                            0x1086e248c thunk for @callee_guaranteed () -> (@error @owned Error) + 20 (<compiler-generated>:20)
13 NIO                            0x10879e638 partial apply for thunk for @callee_guaranteed () -> (@error @owned Error) + 16 (<compiler-generated>:16)
14 NIO                            0x1087a4e98 thunk for @callee_guaranteed () -> (@error @owned Error)partial apply + 12
15 NIO                            0x10879e654 partial apply for specialized closure #1 in withAutoReleasePool<A>(_:) + 20 (<compiler-generated>:20)
16 NIO                            0x1087a4d68 closure #1 in withAutoReleasePool<A>(_:)specialized partial apply + 12
17 libswiftObjectiveC.dylib       0x1b874fc20 autoreleasepool<A>(invoking:) + 64
18 NIO                            0x10879a1cc SelectableEventLoop.run() + 22 (SelectableEventLoop.swift:22)
19 NIO                            0x10874df1c closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:selectorFactory:initializer:) + 824 (EventLoop.swift:824)
20 NIO                            0x1087c0138 thunk for @escaping @callee_guaranteed (@guaranteed NIOThread) -> () + 24 (<compiler-generated>:24)
21 NIO                            0x1087c137c closure #1 in static ThreadOpsPosix.run(handle:args:detachThread:) + 364 (<compiler-generated>:364)
22 libsystem_pthread.dylib        0x1813ef914 _pthread_start + 168
23 libsystem_pthread.dylib        0x1813f79d4 thread_start + 8
@AVVS AVVS added the kind/bug Feature doesn't work as expected. label Aug 21, 2020
@glbrntt
Copy link
Collaborator

glbrntt commented Aug 24, 2020

Thanks for the bug report @AVVS -- I think I've worked out the set of conditions that would lead to this. Knowing a few extra bits of information would add some certainty that I have found the problem you've hit though.

  • The crash you're hitting is a precondition failure: do you have the message for that precondition failure, or any logs?
  • To hit this I think you need your call start behaviour to be .fastFailure -- are you using this setting?

glbrntt added a commit to glbrntt/grpc-swift that referenced this issue Aug 24, 2020
Motivation:

In certain conditions it's possible for a connection to idle when in the
'active' state resulting in a precondition failure.

The active state is not user facing and represents the state where we
have an active connection to a remote peer but have not yet seen the
initial settings frame. It's not usually possible for users to get a
connection in this state since we normally only vend connections in the
'ready' state (where we have seen the initial settings frame). However,
in the 'fastFailure' mode this constraint is lifted.

If keepalive is configured, the connection is in the active state, and
the client starts an RPC then it is possible for the keepalive timeout
to fire, idling the connection before it reaches the ready state,
resulting in a precondition failure.

Modifications:

- Allow the connection manager to idle from the active state

Result:

- Idling from the active state is tolerated
- Resolves grpc#949
Lukasa pushed a commit that referenced this issue Aug 24, 2020
Motivation:

In certain conditions it's possible for a connection to idle when in the
'active' state resulting in a precondition failure.

The active state is not user facing and represents the state where we
have an active connection to a remote peer but have not yet seen the
initial settings frame. It's not usually possible for users to get a
connection in this state since we normally only vend connections in the
'ready' state (where we have seen the initial settings frame). However,
in the 'fastFailure' mode this constraint is lifted.

If keepalive is configured, the connection is in the active state, and
the client starts an RPC then it is possible for the keepalive timeout
to fire, idling the connection before it reaches the ready state,
resulting in a precondition failure.

Modifications:

- Allow the connection manager to idle from the active state

Result:

- Idling from the active state is tolerated
- Resolves #949
@AVVS
Copy link
Author

AVVS commented Aug 24, 2020

We are not using fast failure, but we do use bidi streams - I noticed that the connection may close itself if there is an active bidi stream, but no data has been going back and forth for a while (except for keepalive)

In that case we were making sure a reconnect happens and its generally been good

I sadly dont have the precondition message - crashlytics didnt capture it for some reason

@glbrntt
Copy link
Collaborator

glbrntt commented Aug 24, 2020

We are not using fast failure

That's unfortunate because it makes it highly unlikely I've fixed your bug! Can you provide some more context on this, like the configuration you're using for your client?

but we do use bidi streams - I noticed that the connection may close itself if there is an active bidi stream, but no data has been going back and forth for a while (except for keepalive)

Hmm, how are you observing that? Are you sure this isn't the connection being dropped rather than gRPC actively deciding to close it? We should never close the connection if there are active streams.

@glbrntt glbrntt reopened this Aug 24, 2020
@AVVS
Copy link
Author

AVVS commented Aug 24, 2020

Hmm, how are you observing that? Are you sure this isn't the connection being dropped rather than gRPC actively deciding to close it? We should never close the connection if there are active streams.

Reading delegate logs:

  /// holds grpc NIO chat event loop
  private let chatGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)

  /// holds keepalive configuration for chat
  private let keepalive = ClientConnectionKeepalive(
    interval: .seconds(10),
    timeout: .seconds(5),
    permitWithoutCalls: true,
    maximumPingsWithoutData: 100,
    minimumSentPingIntervalWithoutData: .minutes(1)
  )

  /// holds grpc chat connection manager
  private lazy var chatChannel = ClientConnection
    .secure(group: chatGroup)
    .withKeepalive(keepalive)
    .withConnectionIdleTimeout(.hours(24)) // was default earlier, but was going .ready -> .idle often
    .withErrorDelegate(self)
    .withConnectivityStateDelegate(self)
    .withCallStartBehavior(.waitsForConnectivity)
    .withBackgroundActivityLogger(Logger(label: "slr.chat"))
    .connect(host: Constants.GRPC.chatHost, port: 443)

  private lazy var gRPCChatClient = Pbx_NodeClient(channel: chatChannel)
...

  func didCatchError(_ error: Error, logger: Logger, file: StaticString, line: Int) {
    if let err = error as? IOError {
      SLRLog(level: .error, ["IO chat connection err", err.errnoCode, err.description])
    } else {
      SLRLog(level: .error, ["unexpected chat connection", error.localizedDescription, file, line])
    }
  }

  func connectivityStateDidChange(from oldState: ConnectivityState, to newState: ConnectivityState) {
    SLRLog(level: .info, ["chat connection state change from", oldState, "to", newState])

    // connection closed when it went to .idle
    switch (oldState, newState) {
    case (.ready, .idle), (.ready, .transientFailure):
      chatState.accept(.error(NIOHTTP2Errors.IOOnClosedConnection())) // triggers reconnect -- not sure why this keeps happening
    default: break
    }
  }

Its possible .ready -> .idle would trigger due to maximumPingsWithoutData: 100 now that I'm paying close attention to it so that would probably be normal

Only call that happens with this grpc connection is establishing a bidi loop right away, which is supposed to be active/reconnec

    loop = gRPCChatClient.messageLoop { [weak self] message in
      self?.handleLoop(message)
    }

    loop?.status.whenComplete { result in
      if case .success(let value) = result {
        SLRLog(level: .debug, "[chat][loop] \(value.description) - \(value.code)")
      } else if case .failure(let err) = result {
        SLRLog(level: .debug, "[chat][loop] \(err.localizedDescription)")
      }
    }

Please let me know if there are more details I can provide or anything in the code is worth investigating/changing to reliably trigger the error - its not happening often, but I noticed that about 50% of the time it happens when the device is still in the background mode or would be switching from background to foreground. Assume the connection would be getting cut since the app stops operating in background after a few seconds, at the same time the crash doesnt happen all the time - I havent had it once on my development devices, but crash logs tell that it happens for others

@glbrntt
Copy link
Collaborator

glbrntt commented Aug 25, 2020

Thanks, there are so useful things to note here, I'll leave some comments inline.

  /// holds grpc NIO chat event loop
  private let chatGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)

You should prefer using PlatformSupport.makeEventLoopGroup(loopCount:). The Network.framework implementation is better supported than the sockets-based implementation on iOS devices.

  /// holds keepalive configuration for chat
  private let keepalive = ClientConnectionKeepalive(
    interval: .seconds(10),
    timeout: .seconds(5),
    permitWithoutCalls: true,
    maximumPingsWithoutData: 100,
    minimumSentPingIntervalWithoutData: .minutes(1)
  )

I suspect the pings aren't actually being received by the remote because the app is in the background. It shouldn't be necessary to set the maximumPingsWithoutData that high.

  /// holds grpc chat connection manager
  private lazy var chatChannel = ClientConnection
    .secure(group: chatGroup)
    .withKeepalive(keepalive)
    .withConnectionIdleTimeout(.hours(24)) // was default earlier, but was going .ready -> .idle often
    .withErrorDelegate(self)
    .withConnectivityStateDelegate(self)
    .withCallStartBehavior(.waitsForConnectivity)
    .withBackgroundActivityLogger(Logger(label: "slr.chat"))
    .connect(host: Constants.GRPC.chatHost, port: 443)

The connection is supposed to transition from ready to idle when there are no active RPCs.

  func connectivityStateDidChange(from oldState: ConnectivityState, to newState: ConnectivityState) {
    SLRLog(level: .info, ["chat connection state change from", oldState, "to", newState])

    // connection closed when it went to .idle
    switch (oldState, newState) {
    case (.ready, .idle), (.ready, .transientFailure):
      chatState.accept(.error(NIOHTTP2Errors.IOOnClosedConnection())) // triggers reconnect -- not sure why this keeps happening
    default: break
    }
  }

Just to check: the reconnect you mention here, is this just creating a new RPC? There should be no need to create a new connection here, gRPC will do that for you.

Please let me know if there are more details I can provide or anything in the code is worth investigating/changing to reliably trigger the error - its not happening often, but I noticed that about 50% of the time it happens when the device is still in the background mode or would be switching from background to foreground. Assume the connection would be getting cut since the app stops operating in background after a few seconds, at the same time the crash doesnt happen all the time - I havent had it once on my development devices, but crash logs tell that it happens for others

Can you provide some logs from right before a crash? I think that'd be helpful to see.

glbrntt added a commit to glbrntt/grpc-swift that referenced this issue Aug 25, 2020
Motivation:

Related to grpc#949.

It's possible for the client's connection to be dropped, and for the
connection state to become idle, prior to the scheduled close from the
keepalive handler firing. As the idle handler never updates its state to
'closed' in 'channelInactive', when the scheduled close event is picked
up in the idle handler it effectively ask the connection manager to
double-idle, hitting a precondition failure.

Modifications:

- Move the 'GRPCIdleHandler' to '.closed' in 'channelInactive'
- Cancel scheduled pings and timeouts on 'channelInactive' in the
  'GRPCKeepaliveHandlers'

Result:

- We avoid another path to a precondition failure
glbrntt added a commit to glbrntt/grpc-swift that referenced this issue Aug 25, 2020
Motivation:

Related to grpc#949.

It's possible for the client's connection to be dropped, and for the
connection state to become idle, prior to the scheduled close from the
keepalive handler firing. As the idle handler never updates its state to
'closed' in 'channelInactive', when the scheduled close event is picked
up in the idle handler it effectively ask the connection manager to
double-idle, hitting a precondition failure.

Modifications:

- Move the 'GRPCIdleHandler' to '.closed' in 'channelInactive'
- Cancel scheduled pings and timeouts on 'channelInactive' in the
  'GRPCKeepaliveHandlers'

Result:

- We avoid another path to a precondition failure
glbrntt added a commit that referenced this issue Aug 25, 2020
Motivation:

Related to #949.

It's possible for the client's connection to be dropped, and for the
connection state to become idle, prior to the scheduled close from the
keepalive handler firing. As the idle handler never updates its state to
'closed' in 'channelInactive', when the scheduled close event is picked
up in the idle handler it effectively ask the connection manager to
double-idle, hitting a precondition failure.

Modifications:

- Move the 'GRPCIdleHandler' to '.closed' in 'channelInactive'
- Cancel scheduled pings and timeouts on 'channelInactive' in the
  'GRPCKeepaliveHandlers'

Result:

- We avoid another path to a precondition failure
@AVVS
Copy link
Author

AVVS commented Aug 25, 2020

Just to check: the reconnect you mention here, is this just creating a new RPC? There should be no need to create a new connection here, gRPC will do that for you.

It initiates new bidi stream:

  // onError handler thats closed when accept(.error()) is called
  private func handleError(_ err: Error) {
    SLRLog(level: .error, ["chat connection failed", err])

    guard chatConnectionState != .reconnecting,
          chatConnectionState != .closing else {
      return
    }

    chatConnectionState = .reconnecting
    close().whenComplete { [weak self] _ in
      guard let self = self, let backoff = self.backoffSequence.next()?.backoff else {
        return
      }

      self.connectionGroup.next().scheduleTask(in: .seconds(Int64(backoff))) { [unowned self] in
        self.chatState.accept(.reconnect(err))
      }
    }
  }

This is the closing function, just so you can see that its internal cleanup:

  /// Cleans up current chat connection
  /// - Parameter namespace: .chat
  private func close() -> EventLoopFuture<Void> {
    SLRLog(level: .debug, "[chatState] closing .chat")
    let eventLoop = connectionGroup.next()
    return eventLoop.flatSubmit { [unowned self] in
      guard let loop = self.loop else {
        return eventLoop.makeSucceededFuture(())
      }

      self.responseQueue.flush()
      self.loop = nil

      SLRLog(level: .debug, "[chat] loop exists during close, sending .closeSend()")
      if self.chatChannel.connectivity.state == .ready {
        return loop.sendEnd()
      }

      return eventLoop.makeSucceededFuture(())
    }
  }

And this is the reconnect that eventually happens (error -> closing -> connect):
When this is triggered the grpc connection is "revived" if it was idle. Problem here is that the loop itself was alive (I was monitoring server connection logs and if a connection gets broken there is a cancel/exit log, which wasnt present), so the scenario is:

  1. single BiDi stream is active
  2. connection goes to .idle from .ready
  3. manual reconnection is triggered - earlier on I didnt do that and when was trying to write into the loop it would error out saying stream was already closed (delegate would've moved to .idle state by that time)
private func establishLoop() -> EventLoopFuture<Void> {
    loop = gRPCChatClient.messageLoop { [weak self] message in
      self?.handleLoop(message)
    }

    loop?.status.whenComplete { result in
      if case .success(let value) = result {
        SLRLog(level: .debug, "[chat][loop] \(value.description) - \(value.code)")
      } else if case .failure(let err) = result {
        SLRLog(level: .debug, "[chat][loop] \(err.localizedDescription)")
      }
    }

    return opsGroup.next().makeSucceededFuture(())
  }

I suspect the pings aren't actually being received by the remote because the app is in the background

Thats very likely, which is totally fine and having a connection reestablish is also absolutely fine. Just trying to get that crash out of the way :)


I just figured out that the logs in crashlytics are from old to new... Well, that should make things easier because there are useful things in there. Screenshots with the logs, seems like its following the same pattern. One thing that could be at play here is that remote server connection may be getting completely dropped (we were doing load testing, which would lead to servers dying). At times that seems to be the cause of the connection getting dropped, but at times it seems just the transition from background to foreground

Please note the timestamps as they might give some clue as to when this happened (during normal work or bg/fg transition)
Let me know where to dig next :)

Screen Shot 2020-08-25 at 08 59 47

Screen Shot 2020-08-25 at 08 59 39

Screen Shot 2020-08-25 at 08 59 25

Screen Shot 2020-08-25 at 08 59 07

Screen Shot 2020-08-25 at 08 58 52

Screen Shot 2020-08-25 at 08 58 23

Screen Shot 2020-08-25 at 08 57 52

@glbrntt
Copy link
Collaborator

glbrntt commented Aug 25, 2020

Thanks for all the info! I'm fairly confident that I've now fixed (see #953) the bug you've been hitting. Specifically, it would require the connection to be dropped followed by the scheduled close firing (as a result of the ping not being ack'd). This would hit the precondition failure you've been seeing. It also ties in with your logs since you're seeing the transient failure from the ready state and the error you see just before is "Socket is not connected (errno: 57)" (suggesting the connection was dropped).

@AVVS
Copy link
Author

AVVS commented Aug 26, 2020

Thanks, made a build and we are currently testing it :) will let you know if it reoccurs, hopefully not though!

@glbrntt glbrntt closed this as completed Aug 27, 2020
@bimawa
Copy link

bimawa commented Oct 18, 2022

Guys, I got this issue again on version 1.11.0 :

Thread #17:
0	swift_retain + 60
1	initializeWithCopy for ClientInterceptorContext (<compiler-generated>:0)
2	ClientInterceptorPipeline._invokeReceive(_:onContextAtUncheckedIndex:) (ClientInterceptorPipeline.swift:230)
3	ClientInterceptorPipeline.receive(_:) (ClientInterceptorPipeline.swift:205)
4	ClientTransport._receiveFromChannel(initialMetadata:) (ClientTransport.swift:969)
5	specialized ClientTransport.channelRead(context:data:) (ClientTransport.swift:302)
6	ChannelHandlerContext.invokeChannelRead(_:) (ChannelPipeline.swift:1702)
7	ChannelHandlerContext.fireChannelRead(_:) (ChannelPipeline.swift:1515)
8	GRPCClientChannelHandler.readHeaders(content:context:) (GRPCClientChannelHandler.swift:411)
9	protocol witness for _ChannelInboundHandler.channelRead(context:data:) in conformance GRPCClientChannelHandler (GRPCClientChannelHandler.swift:327)
10	ChannelHandlerContext.invokeChannelRead(_:) (ChannelPipeline.swift:1702)
11	ChannelPipeline.fireChannelRead(_:) (ChannelPipeline.swift:897)
12	HTTP2StreamChannel.deliverPendingReads() (HTTP2StreamChannel.swift:713)
13	HTTP2StreamMultiplexer.channelInactive(context:) (HTTP2StreamChannel.swift:822)
14	ChannelHandlerContext.invokeChannelInactive() (ChannelPipeline.swift:1692)
15	ChannelHandlerContext.fireChannelRegistered() + 32
16	GRPCIdleHandler.channelInactive(context:) (GRPCIdleHandler.swift:283)
17	ChannelHandlerContext.invokeChannelInactive() (ChannelPipeline.swift:1692)
18	ChannelHandlerContext.fireChannelRegistered() + 32
19	protocol witness for _ChannelInboundHandler.channelInactive(context:) in conformance NIOHTTP2Handler (HTTP2ChannelHandler.swift:179)
20	ChannelHandlerContext.invokeChannelInactive() (ChannelPipeline.swift:1692)
21	ChannelPipeline.fireChannelRegistered() + 88
22	specialized StateManagedChannel.close0(error:mode:promise:) (StateManagedChannel.swift:210)
23	specialized HeadChannelHandler.close(context:mode:promise:) (ChannelPipeline.swift:1333)
24	ChannelHandlerContext.invokeClose(mode:promise:) (ChannelPipeline.swift:1823)
25	specialized _ChannelOutboundHandler.close(context:mode:promise:) (ChannelPipeline.swift:1639)
26	ChannelHandlerContext.invokeClose(mode:promise:) (ChannelPipeline.swift:1823)
27	ChannelHandlerContext.invokeClose(mode:promise:) (ChannelPipeline.swift:1825)
28	specialized _ChannelOutboundHandler.close(context:mode:promise:) (ChannelPipeline.swift:1639)
29	ChannelHandlerContext.invokeClose(mode:promise:) (ChannelPipeline.swift:1823)
30	ChannelHandlerContext.close(mode:promise:) (ChannelPipeline.swift:1639)
31	DelegatingErrorHandler.errorCaught(context:error:) (DelegatingErrorHandler.swift:61)
32	ChannelHandlerContext.invokeErrorCaught(_:) (ChannelPipeline.swift:1732)
33	ChannelHandlerContext.fireErrorCaught(_:) (ChannelPipeline.swift:1532)
34	HTTP2StreamMultiplexer.errorCaught(context:error:) (HTTP2StreamMultiplexer.swift:215)
35	ChannelHandlerContext.invokeErrorCaught(_:) (ChannelPipeline.swift:1732)
36	ChannelHandlerContext.fireErrorCaught(_:) (ChannelPipeline.swift:1532)
37	protocol witness for _ChannelInboundHandler.errorCaught(context:error:) in conformance GRPCIdleHandler (GRPCIdleHandler.swift:258)
38	ChannelHandlerContext.invokeErrorCaught(_:) (ChannelPipeline.swift:1732)
39	ChannelHandlerContext.fireErrorCaught(_:) (ChannelPipeline.swift:1532)
40	NIOHTTP2Handler.processOutboundFrame(context:frame:promise:) (HTTP2ChannelHandler.swift:533)
41	NIOHTTP2Handler.writeBufferedFrame(context:frame:promise:) (HTTP2ChannelHandler.swift:422)
42	protocol witness for _ChannelOutboundHandler.write(context:data:promise:) in conformance NIOHTTP2Handler (HTTP2ChannelHandler.swift:202)
43	ChannelHandlerContext.invokeWrite(_:promise:) (ChannelPipeline.swift:1782)
44	ChannelHandlerContext.invokeWrite(_:promise:) (ChannelPipeline.swift:1784)
45	ChannelHandlerContext.write(_:promise:) + 52
46	HTTP2StreamChannel.receiveOutboundFrame(_:promise:) (HTTP2StreamMultiplexer.swift:440)
47	HTTP2StreamChannel.closedWhileOpen() (HTTP2StreamChannel.swift:592)
48	specialized HeadChannelHandler.close(context:mode:promise:) (ChannelPipeline.swift:1333)
49	ChannelHandlerContext.invokeClose(mode:promise:) (ChannelPipeline.swift:1823)
50	specialized _ChannelOutboundHandler.close(context:mode:promise:) (ChannelPipeline.swift:1639)
51	ChannelHandlerContext.invokeClose(mode:promise:) (ChannelPipeline.swift:1823)
52	ChannelHandlerContext.invokeClose(mode:promise:) (ChannelPipeline.swift:1825)
53	ChannelPipeline.close(mode:promise:) (ChannelPipeline.swift:805)
54	Channel.close(mode:promise:) (Channel.swift:197)
55	protocol witness for ChannelOutboundInvoker.close(mode:promise:) in conformance HTTP2StreamChannel (<compiler-generated>:0)
56	ClientTransport._handleError(_:) (ClientTransport.swift:420)
57	ClientTransport._receiveFromChannel(message:) (ClientTransport.swift:463)
58	specialized ClientTransport.channelRead(context:data:) (ClientTransport.swift:305)
59	ChannelHandlerContext.invokeChannelRead(_:) (ChannelPipeline.swift:1702)
60	ChannelHandlerContext.fireChannelRead(_:) (ChannelPipeline.swift:1515)
61	GRPCClientChannelHandler.consumeBytes(from:context:) (GRPCClientChannelHandler.swift:483)
62	GRPCClientChannelHandler.readData(content:context:) (GRPCClientChannelHandler.swift:435)
63	protocol witness for _ChannelInboundHandler.channelRead(context:data:) in conformance GRPCClientChannelHandler (GRPCClientChannelHandler.swift:330)
64	ChannelHandlerContext.invokeChannelRead(_:) (ChannelPipeline.swift:1702)
65	ChannelPipeline.fireChannelRead(_:) (ChannelPipeline.swift:897)
66	HTTP2StreamChannel.deliverPendingReads() (HTTP2StreamChannel.swift:713)
67	HTTP2StreamChannel.receiveStreamClosed(_:) (HTTP2StreamChannel.swift:822)
68	HTTP2StreamMultiplexer.userInboundEventTriggered(context:event:) (MultiplexerAbstractChannel.swift:138)
69	ChannelHandlerContext.invokeUserInboundEventTriggered(_:) (ChannelPipeline.swift:1742)
70	ChannelHandlerContext.fireUserInboundEventTriggered(_:) (ChannelPipeline.swift:1537)
71	GRPCIdleHandler.userInboundEventTriggered(context:event:) (GRPCIdleHandler.swift:248)
72	ChannelHandlerContext.invokeUserInboundEventTriggered(_:) (ChannelPipeline.swift:1742)
73	ChannelHandlerContext.fireUserInboundEventTriggered(_:) (ChannelPipeline.swift:1537)
74	NIOHTTP2Handler.processPendingUserEvents(context:) (HTTP2ChannelHandler.swift:380)
75	NIOHTTP2Handler.processFrame(_:flowControlledLength:context:) (HTTP2ChannelHandler.swift:349)
76	NIOHTTP2Handler.channelRead(context:data:) (HTTP2ChannelHandler.swift:227)
77	ChannelHandlerContext.invokeChannelRead(_:) (ChannelPipeline.swift:1702)
78	ChannelPipeline.fireChannelRead(_:) (ChannelPipeline.swift:897)
79	specialized NIOTSConnectionChannel.dataReceivedHandler(content:context:isComplete:error:) (NIOTSConnectionChannel.swift:732)
80	closure #1 in NWConnection.receiveMessage(completion:) + 164
81	thunk for @escaping @callee_guaranteed (@guaranteed OS_dispatch_data?, @guaranteed OS_nw_content_context?, @unowned Bool, @guaranteed OS_nw_error?) -> () + 104
82	_dispatch_block_async_invoke2 + 144
83	_dispatch_client_callout + 16
84	_dispatch_lane_serial_drain + 668
85	_dispatch_lane_invoke + 432
86	_dispatch_lane_serial_drain + 372
87	_dispatch_lane_invoke + 432
88	_dispatch_workloop_worker_thread + 648
89	_pthread_wqthread + 284
90	start_wqthread + 4

@Lukasa
Copy link
Collaborator

Lukasa commented Oct 18, 2022

Can you please attach the full crash report?

@bimawa
Copy link

bimawa commented Oct 18, 2022

Can you please attach the full crash report?

Yes! ofc.
SLR-227-IQ050p-zta0A7y0JYza-issue-data.txt

@Lukasa
Copy link
Collaborator

Lukasa commented Oct 18, 2022

This crash seems different: a segmentation fault in swift_retain is not likely to be the result of simple mismanagement of state transitions. It seems more likely to be a threading issue.

@bimawa
Copy link

bimawa commented Oct 18, 2022

@Lukasa Ty Lukasa, we will research it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Feature doesn't work as expected.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants