Kitura / Kitura-WebSocket-NIO

A SwiftNIO based implementation of WebSocket for Kitura
Apache License 2.0
18 stars 14 forks source link

TSan error in `KituraWebSocketTests.ConnectionCleanupTests testMultiConnectionTimeOut` #56

Open weissi opened 5 years ago

weissi commented 5 years ago

whilst running the NIO release tools, I found this data race with TSan output.txt :

Test Suite 'ConnectionCleanupTests' started at 2019-10-23 2:13:21.685 pm
Test Case '-[KituraWebSocketTests.ConnectionCleanupTests testMultiConnectionTimeOut]' started.
==================
WARNING: ThreadSanitizer: data race (pid=859)
  Read of size 1 at 0x7b4400083c29 by thread T17:
    #0 WebSocketClient.isConnected.getter <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x487447)
    #1 implicit closure #1 in closure #1 in ConnectionCleanupTests.testMultiConnectionTimeOut() <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x450584)
    #2 partial apply for implicit closure #1 in closure #1 in ConnectionCleanupTests.testMultiConnectionTimeOut() <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x451c47)
    #3 partial apply for closure #1 in XCTAssertTrue(_:_:file:line:) <null>:10181888 (libswiftXCTest.dylib:x86_64+0x10884)
    #4 partial apply for closure #1 in ConnectionCleanupTests.testMultiConnectionTimeOut() <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x45137c)
    #5 thunk for @escaping @callee_guaranteed (@guaranteed XCTestExpectation) -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4025bb)
    #6 thunk for @escaping @callee_guaranteed (@guaranteed XCTestExpectation) -> ()partial apply <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x451428)
    #7 thunk for @escaping @callee_guaranteed (@in_guaranteed XCTestExpectation) -> (@out ()) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x45818b)
    #8 partial apply for thunk for @escaping @callee_guaranteed (@in_guaranteed XCTestExpectation) -> (@out ()) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x458920)
    #9 closure #1 in KituraTest.performServerTest(line:asyncTasks:) KituraTest.swift:58 (KituraWebSocketPackageTests:x86_64+0x45823e)
    #10 partial apply for closure #1 in KituraTest.performServerTest(line:asyncTasks:) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4587ef)
    #11 thunk for @escaping @callee_guaranteed () -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x362ca0)
    #12 __tsan::invoke_and_release_block(void*) <null>:10181888 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x6d65b)
    #13 _dispatch_client_callout <null>:10181888 (libdispatch.dylib:x86_64+0x350d)

  Previous write of size 1 at 0x7b4400083c29 by thread T16:
    #0 WebSocketClient.isConnected.setter <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4874bb)
    #1 WebSocketMessageHandler.channelInactive(context:) WebSocketClient.swift:386 (KituraWebSocketPackageTests:x86_64+0x492a51)
    #2 protocol witness for _ChannelInboundHandler.channelInactive(context:) in conformance WebSocketMessageHandler <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x494973)
    #3 ChannelHandlerContext.invokeChannelInactive() ChannelPipeline.swift:1325 (KituraWebSocketPackageTests:x86_64+0x55ee1f)
    #4 ChannelHandlerContext.fireChannelInactive() ChannelPipeline.swift:1143 (KituraWebSocketPackageTests:x86_64+0x56631a)
    #5 ByteToMessageHandler.channelInactive(context:) Codec.swift:657 (KituraWebSocketPackageTests:x86_64+0x595870)
    #6 protocol witness for _ChannelInboundHandler.channelInactive(context:) in conformance ByteToMessageHandler<A> <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x595d9a)
    #7 ChannelHandlerContext.invokeChannelInactive() ChannelPipeline.swift:1325 (KituraWebSocketPackageTests:x86_64+0x55ee1f)
    #8 ChannelHandlerContext.invokeChannelInactive() ChannelPipeline.swift:1327 (KituraWebSocketPackageTests:x86_64+0x55eec6)
    #9 ChannelPipeline.fireChannelInactive0() ChannelPipeline.swift:817 (KituraWebSocketPackageTests:x86_64+0x5560ab)
    #10 closure #6 in SocketChannelLifecycleManager.moveState(event:) BaseSocketChannel.swift:138 (KituraWebSocketPackageTests:x86_64+0x4ce6ef)
    #11 BaseSocketChannel.close0(error:mode:promise:) BaseSocketChannel.swift:765 (KituraWebSocketPackageTests:x86_64+0x4e24fe)
    #12 BaseStreamSocketChannel.close0(error:mode:promise:) BaseStreamSocketChannel.swift:199 (KituraWebSocketPackageTests:x86_64+0x4f99e6)
    #13 BaseSocketChannel.readable0() BaseSocketChannel.swift:1011 (KituraWebSocketPackageTests:x86_64+0x4eb62a)
    #14 BaseSocketChannel.readEOF0() BaseSocketChannel.swift:905 (KituraWebSocketPackageTests:x86_64+0x4e9962)
    #15 BaseSocketChannel.readEOF() BaseSocketChannel.swift:891 (KituraWebSocketPackageTests:x86_64+0x4e8921)
    #16 protocol witness for SelectableChannel.readEOF() in conformance BaseSocketChannel<A> <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4eeb8c)
    #17 SelectableEventLoop.handleEvent<A>(_:channel:) EventLoop.swift:835 (KituraWebSocketPackageTests:x86_64+0x5c52ac)
    #18 closure #1 in closure #1 in SelectableEventLoop.run() EventLoop.swift:886 (KituraWebSocketPackageTests:x86_64+0x5c6ace)
    #19 partial apply for closure #1 in closure #1 in SelectableEventLoop.run() <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5d7d42)
    #20 thunk for @callee_guaranteed (@guaranteed SelectorEvent<NIORegistration>) -> (@error @owned Error) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5c7031)
    #21 partial apply for thunk for @callee_guaranteed (@guaranteed SelectorEvent<NIORegistration>) -> (@error @owned Error) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5d7daa)
    #22 Selector.whenReady(strategy:_:) Selector.swift:594 (KituraWebSocketPackageTests:x86_64+0x68e043)
    #23 closure #1 in SelectableEventLoop.run() EventLoop.swift:881 (KituraWebSocketPackageTests:x86_64+0x5c66ab)
    #24 partial apply for closure #1 in SelectableEventLoop.run() <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5d2e14)
    #25 thunk for @callee_guaranteed () -> (@error @owned Error) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x49c6df)
    #26 thunk for @callee_guaranteed () -> (@error @owned Error)partial apply <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5d2e87)
    #27 closure #1 in withAutoReleasePool<A>(_:) EventLoop.swift:632 (KituraWebSocketPackageTests:x86_64+0x5c0a28)
    #28 partial apply for closure #1 in withAutoReleasePool<A>(_:) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5d7caa)
    #29 autoreleasepool<A>(invoking:) <null>:10181888 (libswiftObjectiveC.dylib:x86_64+0x2f0d)
    #30 SelectableEventLoop.run() EventLoop.swift:880 (KituraWebSocketPackageTests:x86_64+0x5c58d0)
    #31 closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:initializer:) EventLoop.swift:1106 (KituraWebSocketPackageTests:x86_64+0x5cafba)
    #32 partial apply for closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:initializer:) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5d76d9)
    #33 thunk for @escaping @callee_guaranteed (@guaranteed NIOThread) -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5cb98b)
    #34 partial apply for thunk for @escaping @callee_guaranteed (@guaranteed NIOThread) -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x6d61b8)
    #35 closure #1 in static NIOThread.spawnAndRun(name:detachThread:body:) Thread.swift:110 (KituraWebSocketPackageTests:x86_64+0x6d66a7)
    #36 @objc closure #1 in static NIOThread.spawnAndRun(name:detachThread:body:) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x6d6760)

  As if synchronized via sleep:
    #0 sleep <null>:10182016 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x2940e)
    #1 closure #1 in ConnectionCleanupTests.testMultiConnectionTimeOut() ConnectionCleanupTests.swift:86 (KituraWebSocketPackageTests:x86_64+0x45026f)
    #2 partial apply for closure #1 in ConnectionCleanupTests.testMultiConnectionTimeOut() <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x45137c)
    #3 thunk for @escaping @callee_guaranteed (@guaranteed XCTestExpectation) -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4025bb)
    #4 thunk for @escaping @callee_guaranteed (@guaranteed XCTestExpectation) -> ()partial apply <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x451428)
    #5 thunk for @escaping @callee_guaranteed (@in_guaranteed XCTestExpectation) -> (@out ()) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x45818b)
    #6 partial apply for thunk for @escaping @callee_guaranteed (@in_guaranteed XCTestExpectation) -> (@out ()) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x458920)
    #7 closure #1 in KituraTest.performServerTest(line:asyncTasks:) KituraTest.swift:58 (KituraWebSocketPackageTests:x86_64+0x45823e)
    #8 partial apply for closure #1 in KituraTest.performServerTest(line:asyncTasks:) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4587ef)
    #9 thunk for @escaping @callee_guaranteed () -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x362ca0)
    #10 __tsan::invoke_and_release_block(void*) <null>:10182016 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x6d65b)
    #11 _dispatch_client_callout <null>:10182016 (libdispatch.dylib:x86_64+0x350d)

  Location is heap block of size 272 at 0x7b4400083b80 allocated by thread T17:
    #0 malloc <null>:10181920 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x4e6ba)
    #1 swift_slowAlloc <null>:10181920 (libswiftCore.dylib:x86_64+0x2cd698)
    #2 closure #1 in ConnectionCleanupTests.testMultiConnectionTimeOut() ConnectionCleanupTests.swift:73 (KituraWebSocketPackageTests:x86_64+0x44fe1b)
    #3 partial apply for closure #1 in ConnectionCleanupTests.testMultiConnectionTimeOut() <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x45137c)
    #4 thunk for @escaping @callee_guaranteed (@guaranteed XCTestExpectation) -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4025bb)
    #5 thunk for @escaping @callee_guaranteed (@guaranteed XCTestExpectation) -> ()partial apply <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x451428)
    #6 thunk for @escaping @callee_guaranteed (@in_guaranteed XCTestExpectation) -> (@out ()) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x45818b)
    #7 partial apply for thunk for @escaping @callee_guaranteed (@in_guaranteed XCTestExpectation) -> (@out ()) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x458920)
    #8 closure #1 in KituraTest.performServerTest(line:asyncTasks:) KituraTest.swift:58 (KituraWebSocketPackageTests:x86_64+0x45823e)
    #9 partial apply for closure #1 in KituraTest.performServerTest(line:asyncTasks:) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4587ef)
    #10 thunk for @escaping @callee_guaranteed () -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x362ca0)
    #11 __tsan::invoke_and_release_block(void*) <null>:10181920 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x6d65b)
    #12 _dispatch_client_callout <null>:10181920 (libdispatch.dylib:x86_64+0x350d)

  Thread T17 (tid=4426440, running) is a GCD worker thread

  Thread T16 (tid=4426438, running) created by thread T1 at:
    #0 pthread_create <null>:10181968 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x2aa2d)
    #1 static NIOThread.spawnAndRun(name:detachThread:body:) Thread.swift:96 (KituraWebSocketPackageTests:x86_64+0x6d5628)
    #2 static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:initializer:) EventLoop.swift:1092 (KituraWebSocketPackageTests:x86_64+0x5ca927)
    #3 closure #1 in MultiThreadedEventLoopGroup.init(threadInitializers:) EventLoop.swift:1138 (KituraWebSocketPackageTests:x86_64+0x5cc221)
    #4 partial apply for closure #1 in MultiThreadedEventLoopGroup.init(threadInitializers:) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5d3978)
    #5 thunk for @callee_guaranteed (@guaranteed @escaping @callee_guaranteed (@guaranteed NIOThread) -> ()) -> (@owned SelectableEventLoop, @error @owned Error) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5cc3b0)
    #6 partial apply for thunk for @callee_guaranteed (@guaranteed @escaping @callee_guaranteed (@guaranteed NIOThread) -> ()) -> (@owned SelectableEventLoop, @error @owned Error) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x5d39f2)
    #7 Collection.map<A>(_:) <null>:10181968 (libswiftCore.dylib:x86_64+0xf7de)
    #8 MultiThreadedEventLoopGroup.__allocating_init(threadInitializers:) EventLoop.swift (KituraWebSocketPackageTests:x86_64+0x5cba0f)
    #9 MultiThreadedEventLoopGroup.__allocating_init(numberOfThreads:) EventLoop.swift:1126 (KituraWebSocketPackageTests:x86_64+0x5cb8bf)
    #10 globalinit_33_4B2E60779445D0917734BF975944F759_func0 WebSocketClient.swift:30 (KituraWebSocketPackageTests:x86_64+0x4844cc)
    #11 dispatch_once <null>:10181968 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x6ded4)
    #12 dispatch_once_f <null>:10181968 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x6dfc0)
    #13 swift_once <null>:10181968 (libswiftCore.dylib:x86_64+0x2f42d8)
    #14 WebSocketClient.init(host:port:uri:requestKey:negotiateCompression:maxWindowBits:contextTakeover:maxFrameSize:onOpen:) WebSocketClient.swift:87 (KituraWebSocketPackageTests:x86_64+0x485eb2)
    #15 WebSocketClient.__allocating_init(host:port:uri:requestKey:negotiateCompression:maxWindowBits:contextTakeover:maxFrameSize:onOpen:) WebSocketClient.swift (KituraWebSocketPackageTests:x86_64+0x485a6b)
    #16 KituraTest.createClient(negotiateCompression:uri:contextTakeover:requestKey:) KituraTest.swift:74 (KituraWebSocketPackageTests:x86_64+0x458c87)
    #17 closure #1 in BasicTests.testBinaryLongMessage() BasicTests.swift:61 (KituraWebSocketPackageTests:x86_64+0x401508)
    #18 partial apply for closure #1 in BasicTests.testBinaryLongMessage() <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4017f4)
    #19 thunk for @escaping @callee_guaranteed (@guaranteed XCTestExpectation) -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4025bb)
    #20 partial apply for thunk for @escaping @callee_guaranteed (@guaranteed XCTestExpectation) -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x402668)
    #21 thunk for @escaping @callee_guaranteed (@in_guaranteed XCTestExpectation) -> (@out ()) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x45818b)
    #22 partial apply for thunk for @escaping @callee_guaranteed (@in_guaranteed XCTestExpectation) -> (@out ()) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x458920)
    #23 closure #1 in KituraTest.performServerTest(line:asyncTasks:) KituraTest.swift:58 (KituraWebSocketPackageTests:x86_64+0x45823e)
    #24 partial apply for closure #1 in KituraTest.performServerTest(line:asyncTasks:) <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x4587ef)
    #25 thunk for @escaping @callee_guaranteed () -> () <compiler-generated> (KituraWebSocketPackageTests:x86_64+0x362ca0)
    #26 __tsan::invoke_and_release_block(void*) <null>:10181968 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x6d65b)
    #27 _dispatch_client_callout <null>:10181968 (libdispatch.dylib:x86_64+0x350d)

SUMMARY: ThreadSanitizer: data race <compiler-generated> in WebSocketClient.isConnected.getter
==================
Test Case '-[KituraWebSocketTests.ConnectionCleanupTests testMultiConnectionTimeOut]' passed (4.936 seconds).
weissi commented 5 years ago

all the SHAs were:

Kitura-NIO: 69bd82be54207512bee5baf374f461fe83190b2e
Kitura-WebSocket-NIO: 0c4037a6f102396b664959a0589c6b2126dd00a2
swift-nio: 8066b0f581604e3711979307a4377457e2b0f007
swift-nio-extras: 0584020dcacfa932f66b00cfbf87588ead76a528
swift-nio-http2: 97e8bbbcf8184121913ee6a3cf4bf518a87dda5c
swift-nio-ssl: 37cbb1653c6e3ed170c920772e4e4e3fd152f333
swift-nio-transport-services: 4add2df50168b39196b4c66f99e254d49bad469c
harish1992 commented 4 years ago

Hi @weissi, this issue has been fixed in PR #57.