apple / swift-protobuf

Plugin and runtime library for using protobuf with Swift
Apache License 2.0
4.56k stars 449 forks source link

EXC_BAD_ACCESS on NameMap init #1014

Open nanocba opened 4 years ago

nanocba commented 4 years ago

Our app is crashing while trying to convert from JSON with an EXC_BAD_ACCESS on one of the _protobuf_nameMap of our protos.

It crashes for a specific proto (others work just fine). At first we thought the JSON may be off, our swift protos were off, but we discarded that after double checking everything looked good on that front. Then I enabled the address sanitizer diagnostic tool and surprinsingly leaving it enabled makes the app to stop crashing which lead us to believe this is not strictly related to the parsing of our models, but instead a memory related issue.

This is the proto where the app crashes:

extension Documents_Analysis.AnalysisStatus: SwiftProtobuf._ProtoNameProviding {
  static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
    0: .same(proto: "UNKNOWN"),
    25: .same(proto: "PENDING"),
    50: .same(proto: "FAILED"),
    100: .same(proto: "PENDING_REANALYSIS"),
    150: .same(proto: "FAILED_REANALYSIS"),
    200: .same(proto: "COMPLETE"),
  ]
}

This is the model we are trying to convert from, specifically where the status field lives:

"2": {
           "status": "COMPLETE",
           "attemptedAt": "1592934740434",
           "finishedAt": "1592934749539"
}

The EXC_BAD_ACCESS crash happens on the initializer of the NameMap struct:

public init(dictionaryLiteral elements: (Int, NameDescription)...)

Here's full stack trace:

* thread #11, queue = 'NSOperationQueue 0x7fc630076ef0 (QOS: UNSPECIFIED)', stop reason = EXC_BAD_ACCESS (code=2, address=0x700005c00e58)
  * frame #0: 0x000000010b14bb5f SwiftProtobuf`_NameMap.init(elements=0 values) at NameMap.swift:200
    frame #1: 0x00000001055ec13b Glide`globalinit_33_9D177058F711AF21B7E804C5F0EDD592_func88 at documents.pb.swift:4285:58
    frame #2: 0x000000010e45dd48 libdispatch.dylib`_dispatch_client_callout + 8
    frame #3: 0x000000010e45f297 libdispatch.dylib`_dispatch_once_callout + 66
    frame #4: 0x000000010db4d669 libswiftCore.dylib`swift_once + 25
    frame #5: 0x00000001055ec184 Glide`Documents_Analysis.AnalysisStatus._protobuf_nameMap.unsafeMutableAddressor at documents.pb.swift:4285:14
    frame #6: 0x00000001055ec19d Glide`static Documents_Analysis.AnalysisStatus._protobuf_nameMap.getter at <compiler-generated>:0
    frame #7: 0x00000001055ec219 Glide`protocol witness for static _ProtoNameProviding._protobuf_nameMap.getter in conformance Documents_Analysis.AnalysisStatus at <compiler-generated>:0
    frame #8: 0x000000010b0d339f SwiftProtobuf`Enum.init(rawUTF8=Swift.UnsafeRawBufferPointer @ 0x0000700005c023a0) at Enum.swift:88:34
    frame #9: 0x000000010b140bc8 SwiftProtobuf`JSONScanner.nextEnumValue<E>(self=SwiftProtobuf.JSONScanner @ 0x0000700005c03070) at JSONScanner.swift:1295:20
    frame #10: 0x000000010b112232 SwiftProtobuf`JSONDecoder.decodeSingularEnumField<E>(value=unknown, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c03070) at JSONDecoder.swift:478:25
    frame #11: 0x000000010b11792f SwiftProtobuf`protocol witness for Decoder.decodeSingularEnumField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #12: 0x00000001055eda9f Glide`Documents_Analysis.AnalysisState.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c03070, self=Glide.Documents_Analysis.AnalysisState @ 0x0000700005c03230) at documents.pb.swift:4341:27
    frame #13: 0x00000001055ee6bf Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Documents_Analysis.AnalysisState at <compiler-generated>:0
    frame #14: 0x000000010b112999 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Documents_Analysis.AnalysisState @ 0x0000700005c03230, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c03070) at JSONDecoder.swift:514:19
    frame #15: 0x000000010b11339b SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c046e0) at JSONDecoder.swift:533:20
    frame #16: 0x000000010b115fd2 SwiftProtobuf`JSONDecoder.decodeMapField<KeyType, ValueType>(fieldType=SwiftProtobuf._ProtobufMessageMap<SwiftProtobuf.ProtobufInt32, Glide.Documents_Analysis.AnalysisState>, value=Swift.Dictionary<Swift.Int32, Glide.Documents_Analysis.AnalysisState> @ 0x0000700005c38838, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c046e0) at JSONDecoder.swift:682:11
    frame #17: 0x000000010b117c8f SwiftProtobuf`protocol witness for Decoder.decodeMapField<A, B>(fieldType:value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #18: 0x00000001055e9754 Glide`Documents_Analysis.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c046e0, self=Glide.Documents_Analysis @ 0x0000700005c387e8) at documents.pb.swift:4220:27
    frame #19: 0x00000001055ebbcf Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Documents_Analysis at <compiler-generated>:0
    frame #20: 0x000000010b112999 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Documents_Analysis @ 0x0000700005c387e8, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c046e0) at JSONDecoder.swift:514:19
    frame #21: 0x000000010b11339b SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c05e20) at JSONDecoder.swift:533:20
    frame #22: 0x000000010b117a4f SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #23: 0x0000000105598fc9 Glide`Documents_Document.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c05e20, self=Glide.Documents_Document @ 0x0000700005c38700) at documents.pb.swift:2152:30
    frame #24: 0x000000010559ba4f Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Documents_Document at <compiler-generated>:0
    frame #25: 0x000000010b112999 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Documents_Document @ 0x0000700005c38700, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c05e20) at JSONDecoder.swift:514:19
    frame #26: 0x000000010b11339b SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c079e0) at JSONDecoder.swift:533:20
    frame #27: 0x000000010b117a4f SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #28: 0x00000001065ed767 Glide`Transactions_Item.TransactionDocumentVersion.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c079e0, self=Glide.Transactions_Item.TransactionDocumentVersion @ 0x0000700005c386a0) at transactions.pb.swift:31551:27
    frame #29: 0x00000001065eea3f Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Transactions_Item.TransactionDocumentVersion at <compiler-generated>:0
    frame #30: 0x000000010b112999 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Transactions_Item.TransactionDocumentVersion @ 0x0000700005c386a0, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c079e0) at JSONDecoder.swift:514:19
    frame #31: 0x000000010b11339b SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c42e50) at JSONDecoder.swift:533:20
    frame #32: 0x000000010b117a4f SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #33: 0x00000001064ab3a0 Glide`closure #1 in Transactions_Item.decodeMessage<D>(_storage=0x00007fc62f0bb800, decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c42e50) at transactions.pb.swift:29970:23
    frame #34: 0x0000000106773bbf Glide`partial apply for closure #1 in Transactions_Item.decodeMessage<A>(decoder:) at <compiler-generated>:0
    frame #35: 0x0000000106578bb2 Glide`thunk for @callee_guaranteed (@guaranteed Transactions_Item._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #36: 0x0000000106773be4 Glide`partial apply for thunk for @callee_guaranteed (@guaranteed Transactions_Item._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #37: 0x000000010d97d31c libswiftCore.dylib`Swift.withExtendedLifetime<A, B>(A, (A) throws -> B) throws -> B + 12
    frame #38: 0x000000010646f4b9 Glide`Transactions_Item.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c42e50, self=Glide.Transactions_Item @ 0x00007fc633664618) at transactions.pb.swift:29897:9
    frame #39: 0x00000001065b4e7f Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Transactions_Item at <compiler-generated>:0
    frame #40: 0x000000010b112999 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Transactions_Item @ 0x00007fc633664618, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c42e50) at JSONDecoder.swift:514:19
    frame #41: 0x000000010b11339b SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c43dd0) at JSONDecoder.swift:533:20
    frame #42: 0x000000010b117a4f SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #43: 0x00000001065e1bed Glide`closure #1 in Transactions_Item.TransactionDocument.decodeMessage<D>(_storage=0x00007fc633664390, decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c43dd0) at transactions.pb.swift:31312:30
    frame #44: 0x000000010677416f Glide`partial apply for closure #1 in Transactions_Item.TransactionDocument.decodeMessage<A>(decoder:) at <compiler-generated>:0
    frame #45: 0x00000001065e2992 Glide`thunk for @callee_guaranteed (@guaranteed Transactions_Item.TransactionDocument._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #46: 0x0000000106774194 Glide`partial apply for thunk for @callee_guaranteed (@guaranteed Transactions_Item.TransactionDocument._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #47: 0x000000010d97d31c libswiftCore.dylib`Swift.withExtendedLifetime<A, B>(A, (A) throws -> B) throws -> B + 12
    frame #48: 0x00000001065e16b9 Glide`Transactions_Item.TransactionDocument.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c43dd0, self=Glide.Transactions_Item.TransactionDocument @ 0x0000700005c714c0) at transactions.pb.swift:31306:9
    frame #49: 0x00000001065e9a8f Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Transactions_Item.TransactionDocument at <compiler-generated>:0
    frame #50: 0x000000010b112999 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Transactions_Item.TransactionDocument @ 0x0000700005c714c0, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c43dd0) at JSONDecoder.swift:514:19
    frame #51: 0x000000010b11339b SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c7f270) at JSONDecoder.swift:533:20
    frame #52: 0x000000010b117a4f SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #53: 0x0000000106474845 Glide`closure #1 in Transactions_Item.decodeMessage<D>(_storage=0x00007fc62f124000, decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c7f270) at transactions.pb.swift:29914:23
    frame #54: 0x0000000106773bbf Glide`partial apply for closure #1 in Transactions_Item.decodeMessage<A>(decoder:) at <compiler-generated>:0
    frame #55: 0x0000000106578bb2 Glide`thunk for @callee_guaranteed (@guaranteed Transactions_Item._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #56: 0x0000000106773be4 Glide`partial apply for thunk for @callee_guaranteed (@guaranteed Transactions_Item._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #57: 0x000000010d97d31c libswiftCore.dylib`Swift.withExtendedLifetime<A, B>(A, (A) throws -> B) throws -> B + 12
    frame #58: 0x000000010646f4b9 Glide`Transactions_Item.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c7f270, self=Glide.Transactions_Item @ 0x0000700005c7ef90) at transactions.pb.swift:29897:9
    frame #59: 0x00000001065b4e7f Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Transactions_Item at <compiler-generated>:0
    frame #60: 0x000000010b112999 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Transactions_Item @ 0x0000700005c7ef90, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c7f270) at JSONDecoder.swift:514:19
    frame #61: 0x000000010b113db9 SwiftProtobuf`JSONDecoder.decodeRepeatedMessageField<M>(value=0 values, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c7fb70) at JSONDecoder.swift:564:24
    frame #62: 0x000000010b117aaf SwiftProtobuf`protocol witness for Decoder.decodeRepeatedMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #63: 0x000000010679c751 Glide`Transactions_ItemList.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700005c7fb70, self=Glide.Transactions_ItemList @ 0x0000700005c7fdc0) at transactions.pb.swift:39979:28
    frame #64: 0x000000010679d37f Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Transactions_ItemList at <compiler-generated>:0
    frame #65: 0x000000010b112999 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Transactions_ItemList @ 0x0000700005c7fdc0, self=SwiftProtobuf.JSONDecoder @ 0x0000700005c7fb70) at JSONDecoder.swift:514:19
    frame #66: 0x000000010b146cef SwiftProtobuf`closure #1 in Message.init(body=Swift.UnsafeRawBufferPointer @ 0x0000700005c7fc00, options=(messageDepthLimit = 100, ignoreUnknownFields = true), self=Glide.Transactions_ItemList @ 0x0000700005c7fdc0) at Message+JSONAdditions.swift:109:21
    frame #67: 0x000000010b146f04 SwiftProtobuf`partial apply for closure #1 in Message.init(jsonUTF8Data:options:) at <compiler-generated>:0
    frame #68: 0x000000010b01f3ff SwiftProtobuf`thunk for @callee_guaranteed (@unowned UnsafeRawBufferPointer) -> (@error @owned Error) at <compiler-generated>:0
    frame #69: 0x000000010b146f24 SwiftProtobuf`partial apply for thunk for @callee_guaranteed (@unowned UnsafeRawBufferPointer) -> (@error @owned Error) at <compiler-generated>:0
    frame #70: 0x000000010dfc4541 libswiftFoundation.dylib`Foundation.Data.withUnsafeBytes<A>((Swift.UnsafeRawBufferPointer) throws -> A) throws -> A + 593
    frame #71: 0x000000010b146631 SwiftProtobuf`Message.init(jsonUTF8Data=5009 bytes, options=(messageDepthLimit = 100, ignoreUnknownFields = true)) at Message+JSONAdditions.swift:95:22
    frame #72: 0x000000010698bdcf Glide`closure #1 in closure #1 in static APIClient.performRequest<T>(data=5325 bytes, completion=0x000000010a635d00 PromisedFuture`partial apply forwarder for closure #1 (PromisedFuture.Result<A>) -> () in PromisedFuture.Future.execute(onSuccess: (A) -> (), onFailure: Swift.Optional<(Swift.Error) -> ()>) -> () at <compiler-generated>) at APIClient.swift:31:47
    frame #73: 0x00000001053d432f Glide`closure #2 in static NetworkLayer.request(response=0x0000600003461780, data=5325 bytes, success=0x00000001069964b0 Glide`partial apply forwarder for closure #1 (Foundation.Data) -> () in closure #1 ((PromisedFuture.Result<A>) -> ()) -> () in static Glide.APIClient.(performRequest in _E6A5AB6502970C53E0A3D9818D5E84D9)<A where A: SwiftProtobuf.Message>(route: Glide.ApiRouter, cached: Swift.Bool) -> PromisedFuture.Future<A> at <compiler-generated>, cached=false, cache=0x00006000037ce400, urlRequest=Foundation.URLRequest @ 0x000060000349bd10) at NetworkLayer.swift:126:17
    frame #74: 0x00000001053d5801 Glide`partial apply for closure #2 in static NetworkLayer.request(router:cached:success:failure:) at <compiler-generated>:0
    frame #75: 0x00000001053d09b8 Glide`closure #1 in static NetworkLayer.performRequest(data=5325 bytes, response=0x0000600003461780, error=nil, failure=0x0000000106996520 Glide`partial apply forwarder for closure #2 (Swift.Error) -> () in closure #1 ((PromisedFuture.Result<A>) -> ()) -> () in static Glide.APIClient.(performRequest in _E6A5AB6502970C53E0A3D9818D5E84D9)<A where A: SwiftProtobuf.Message>(route: Glide.ApiRouter, cached: Swift.Bool) -> PromisedFuture.Future<A> at <compiler-generated>, success=0x00000001053d57d0 Glide`partial apply forwarder for closure #2 (__C.NSURLResponse, Foundation.Data) -> () in static Glide.NetworkLayer.request(router: Glide.ApiRouter, cached: Swift.Bool, success: (Foundation.Data) -> (), failure: (Swift.Error) -> ()) -> () at <compiler-generated>) at NetworkLayer.swift:93:13
    frame #76: 0x00000001053d6439 Glide`partial apply for closure #1 in static NetworkLayer.performRequest(urlRequest:success:failure:) at <compiler-generated>:0
    frame #77: 0x00000001053d33f3 Glide`thunk for @escaping @callee_guaranteed (@guaranteed Data?, @guaranteed NSURLResponse?, @guaranteed Error?) -> () at <compiler-generated>:0
    frame #78: 0x000000010e9c71f8 CFNetwork`___lldb_unnamed_symbol246$$CFNetwork + 285
    frame #79: 0x000000010e9da3a6 CFNetwork`___lldb_unnamed_symbol689$$CFNetwork + 193
    frame #80: 0x0000000109f74d51 Foundation`__NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
    frame #81: 0x0000000109f74c49 Foundation`-[NSBlockOperation main] + 98
    frame #82: 0x0000000109f77bd6 Foundation`__NSOPERATION_IS_INVOKING_MAIN__ + 17
    frame #83: 0x0000000109f73e49 Foundation`-[NSOperation start] + 731
    frame #84: 0x0000000109f78530 Foundation`__NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__ + 17
    frame #85: 0x0000000109f7803a Foundation`__NSOQSchedule_f + 182
    frame #86: 0x000000010e46c3c9 libdispatch.dylib`_dispatch_block_async_invoke2 + 83
    frame #87: 0x000000010e45dd48 libdispatch.dylib`_dispatch_client_callout + 8
    frame #88: 0x000000010e4606ba libdispatch.dylib`_dispatch_continuation_pop + 552
    frame #89: 0x000000010e45fac5 libdispatch.dylib`_dispatch_async_redirect_invoke + 849
    frame #90: 0x000000010e46f28c libdispatch.dylib`_dispatch_root_queue_drain + 351
    frame #91: 0x000000010e46fb96 libdispatch.dylib`_dispatch_worker_thread2 + 132
    frame #92: 0x000000010e9ab6b3 libsystem_pthread.dylib`_pthread_wqthread + 583
    frame #93: 0x000000010e9ab3fd libsystem_pthread.dylib`start_wqthread + 13

I'm developing on MacOS Mojave using 1.8.0. Tried also with Xcode 11.5, Catalina OS and 1.9.0 and it crashes in the same place.

thomasvl commented 4 years ago

This sounds a little like #1013. But without a repo case, it is sorta hard to tell what is happening. Can you make a isolated sample that shows it?

nanocba commented 4 years ago

This sounds a little like #1013. But without a repo case, it is sorta hard to tell what is happening. Can you make a isolated sample that shows it?

Thanks for the quick reply! I can definitely work on isolating this with a minimal example. Just to mention this is happening under debug configuration. Just to highlight a difference from issue you referenced. I have not yet tried it on a release configuration. Enabling address sanitizer makes it work as expected. Also tried with latest Xcode and OS version and same crash happens which also differs from the description on the referenced issue.

thomasvl commented 4 years ago

What version of Mojave are you on? Are you fully up to date? I think it was 10.14.4 that Apple changed around handing the the Swift runtime (shipping it with the OS), so if you're in an odd state where the Xcode tooling expects it to be handled differently from what your OS version does, it could lead to odd crashes.

nanocba commented 4 years ago

I'm particularly on 10.14.6, but as I said this was also tested using latest tooling available leading to the same crash.

thomasvl commented 4 years ago

Ok, just wanted to check since I realized I'd hit issues trying to use old Xcode versions to recheck things. In any case, a repo case would be great, especially since you say you can get it on current versions.

nanocba commented 4 years ago

thanks for hanging in there! I'm running latest on all fronts now. SwiftProtobuf is at 1.9.0, protoc is 3.12.3, running everything on Mac OS 10.15.5 and using Xcode 11.5. The app is still crashing but I believe is stopping now at a different point that's letting me get more information.

mutating func decodeSingularInt32Field(value: inout Int32) throws {
    if scanner.skipOptionalNull() {
      value = 0
      return
    }
    let n = try scanner.nextSInt()
    if n > Int64(Int32.max) || n < Int64(Int32.min) {
      throw JSONDecodingError.numberRange
    }
    value = Int32(truncatingIfNeeded: n) 
  }

The crash still comes from a EXC_BAD_ACCESS on this line:

 value = Int32(truncatingIfNeeded: n)

The call to that code comes from here:

mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
    while let fieldNumber = try decoder.nextFieldNumber() {
      switch fieldNumber {
      case 1: try decoder.decodeSingularMessageField(value: &self._pdf)
      case 2: try decoder.decodeSingularInt32Field(value: &self.pageCount)
      case 3: try decoder.decodeSingularStringField(value: &self.thumbnailURL)
      case 4: try decoder.decodeSingularStringField(value: &self.hexdigest)
      default: break
      }
    }
  }

In particular, this line:

      case 2: try decoder.decodeSingularInt32Field(value: &self.pageCount)

The source proto is:

message DocumentAnalysisResult {
    PDFDocumentAnalysis pdf = 1 [(jsonfield).visible="never"];
    int32 page_count = 2;
    string thumbnail_url = 3;
    string hexdigest = 4;
}

While PDFDocumentAnalysis proto looks like this:

message PDFDocumentAnalysis {
    repeated google.protobuf.Struct info = 1;
    string ds_tracking_info_xml = 2;
    string ds_envelope_status_xml = 3;
    string ds_envelope_id = 4;
    string ds_document_id = 5;
    string ds_envelope_status = 6;
}

Important point to highlight is that it only crashes when the decoding is being done on a background thread. If I run it on the main thread, it just works.

Here's the complete backtrace of this run:

thread #6, queue = 'com.apple.root.default-qos', stop reason = EXC_BAD_ACCESS (code=2, address=0x7000086e5ff8)
    frame #0: 0x00007fff51368484 libswiftCore.dylib`swift::_gatherGenericParameterCounts(swift::TargetContextDescriptor<swift::InProcess> const*, llvm::SmallVectorImpl<unsigned int>&, swift::Demangle::Demangler&) + 36
    frame #1: 0x00007fff51370513 libswiftCore.dylib`_gatherGenericParameters(swift::TargetContextDescriptor<swift::InProcess> const*, llvm::ArrayRef<swift::TargetMetadata<swift::InProcess> const*>, swift::TargetMetadata<swift::InProcess> const*, llvm::SmallVectorImpl<unsigned int>&, llvm::SmallVectorImpl<void const*>&, swift::Demangle::Demangler&) + 51
    frame #2: 0x00007fff5136ef1c libswiftCore.dylib`(anonymous namespace)::DecodedMetadataBuilder::createBoundGenericType(swift::TargetContextDescriptor<swift::InProcess> const*, llvm::ArrayRef<swift::TargetMetadata<swift::InProcess> const*>, swift::TargetMetadata<swift::InProcess> const*) const + 124
    frame #3: 0x00007fff5136d930 libswiftCore.dylib`swift::Demangle::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::Node*) + 2784
    frame #4: 0x00007fff5136ae5b libswiftCore.dylib`swift_getTypeByMangledNodeImpl(swift::MetadataRequest, swift::Demangle::Demangler&, swift::Demangle::Node*, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 411
    frame #5: 0x00007fff5136ac62 libswiftCore.dylib`swift::swift_getTypeByMangledNode(swift::MetadataRequest, swift::Demangle::Demangler&, swift::Demangle::Node*, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 482
    frame #6: 0x00007fff5136b2c5 libswiftCore.dylib`swift_getTypeByMangledNameImpl(swift::MetadataRequest, llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 997
    frame #7: 0x00007fff51368a22 libswiftCore.dylib`swift::swift_getTypeByMangledName(swift::MetadataRequest, llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 482
    frame #8: 0x00007fff5135c7ac libswiftCore.dylib`swift_getAssociatedTypeWitnessSlowImpl(swift::MetadataRequest, swift::TargetWitnessTable<swift::InProcess>*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolRequirement<swift::InProcess> const*, swift::TargetProtocolRequirement<swift::InProcess> const*) + 428
    frame #9: 0x00007fff5135ad18 libswiftCore.dylib`swift_getAssociatedTypeWitness + 152
    frame #10: 0x00007fff5131dac4 libswiftCore.dylib`type metadata completion function for Swift.IndexingIterator + 84
    frame #11: 0x00007fff5135edcd libswiftCore.dylib`swift::MetadataCacheEntryBase<(anonymous namespace)::GenericCacheEntry, void const*>::doInitialization(swift::ConcurrencyControl&, swift::MetadataCompletionQueueEntry*, swift::MetadataRequest) + 269
    frame #12: 0x00007fff513559c4 libswiftCore.dylib`swift_getGenericMetadata + 1476
    frame #13: 0x00007fff5131ce5d libswiftCore.dylib`__swift_instantiateGenericMetadata + 29
    frame #14: 0x00007fff5136efb4 libswiftCore.dylib`(anonymous namespace)::DecodedMetadataBuilder::createBoundGenericType(swift::TargetContextDescriptor<swift::InProcess> const*, llvm::ArrayRef<swift::TargetMetadata<swift::InProcess> const*>, swift::TargetMetadata<swift::InProcess> const*) const + 276
    frame #15: 0x00007fff5136dfd2 libswiftCore.dylib`swift::Demangle::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::Node*) + 4482
    frame #16: 0x00007fff5136ae5b libswiftCore.dylib`swift_getTypeByMangledNodeImpl(swift::MetadataRequest, swift::Demangle::Demangler&, swift::Demangle::Node*, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 411
    frame #17: 0x00007fff5136ac62 libswiftCore.dylib`swift::swift_getTypeByMangledNode(swift::MetadataRequest, swift::Demangle::Demangler&, swift::Demangle::Node*, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 482
    frame #18: 0x00007fff5136b2c5 libswiftCore.dylib`swift_getTypeByMangledNameImpl(swift::MetadataRequest, llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 997
    frame #19: 0x00007fff51368a22 libswiftCore.dylib`swift::swift_getTypeByMangledName(swift::MetadataRequest, llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 482
    frame #20: 0x00007fff5135c7ac libswiftCore.dylib`swift_getAssociatedTypeWitnessSlowImpl(swift::MetadataRequest, swift::TargetWitnessTable<swift::InProcess>*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolRequirement<swift::InProcess> const*, swift::TargetProtocolRequirement<swift::InProcess> const*) + 428
    frame #21: 0x00007fff5135ad18 libswiftCore.dylib`swift_getAssociatedTypeWitness + 152
    frame #22: 0x00007fff5105a8fa libswiftCore.dylib`(extension in Swift):Swift.FixedWidthInteger.init<A where A1: Swift.BinaryInteger>(truncatingIfNeeded: A1) -> A + 186
    frame #23: 0x000000010cfb70ce SwiftProtobuf`JSONDecoder.decodeSingularInt32Field(value=0, self=SwiftProtobuf.JSONDecoder @ 0x00007000086e9dc0) at JSONDecoder.swift:132:13
    frame #24: 0x000000010cfbe6cd SwiftProtobuf`protocol witness for Decoder.decodeSingularInt32Field(value:) in conformance JSONDecoder at <compiler-generated>:0
  * frame #25: 0x0000000108dccc62 Glide`Documents_DocumentAnalysisResult.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x00007000086e9dc0, self=Glide.Documents_DocumentAnalysisResult @ 0x000070000871e9e0) at documents.pb.swift:4000:27
    frame #26: 0x0000000108dce1ed Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Documents_DocumentAnalysisResult at <compiler-generated>:0
    frame #27: 0x000000010cfba725 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Documents_DocumentAnalysisResult @ 0x000070000871e9e0, self=SwiftProtobuf.JSONDecoder @ 0x00007000086e9dc0) at JSONDecoder.swift:514:19
    frame #28: 0x000000010cfbb084 SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x00007000086eae80) at JSONDecoder.swift:533:20
    frame #29: 0x000000010cfbf14d SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #30: 0x0000000108dd6c46 Glide`Documents_Analysis.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x00007000086eae80, self=Glide.Documents_Analysis @ 0x000070000871e928) at documents.pb.swift:4247:27
    frame #31: 0x0000000108dd9d1d Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Documents_Analysis at <compiler-generated>:0
    frame #32: 0x000000010cfba725 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Documents_Analysis @ 0x000070000871e928, self=SwiftProtobuf.JSONDecoder @ 0x00007000086eae80) at JSONDecoder.swift:514:19
    frame #33: 0x000000010cfbb084 SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x00007000086ec490) at JSONDecoder.swift:533:20
    frame #34: 0x000000010cfbf14d SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #35: 0x0000000108d7be19 Glide`Documents_Document.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x00007000086ec490, self=Glide.Documents_Document @ 0x000070000871e840) at documents.pb.swift:2162:30
    frame #36: 0x0000000108d7f77d Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Documents_Document at <compiler-generated>:0
    frame #37: 0x000000010cfba725 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Documents_Document @ 0x000070000871e840, self=SwiftProtobuf.JSONDecoder @ 0x00007000086ec490) at JSONDecoder.swift:514:19
    frame #38: 0x000000010cfbb084 SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x00007000086edf60) at JSONDecoder.swift:533:20
    frame #39: 0x000000010cfbf14d SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #40: 0x0000000109e2ae97 Glide`Transactions_Item.TransactionDocumentVersion.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x00007000086edf60, self=Glide.Transactions_Item.TransactionDocumentVersion @ 0x000070000871e7e0) at transactions.pb.swift:31628:27
    frame #41: 0x0000000109e2c9fd Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Transactions_Item.TransactionDocumentVersion at <compiler-generated>:0
    frame #42: 0x000000010cfba725 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Transactions_Item.TransactionDocumentVersion @ 0x000070000871e7e0, self=SwiftProtobuf.JSONDecoder @ 0x00007000086edf60) at JSONDecoder.swift:514:19
    frame #43: 0x000000010cfbb084 SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x0000700008728ef0) at JSONDecoder.swift:533:20
    frame #44: 0x000000010cfbf14d SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #45: 0x0000000109ce4d6e Glide`closure #1 in Transactions_Item.decodeMessage<D>(_storage=0x00007fd867018000, decoder=SwiftProtobuf.JSONDecoder @ 0x0000700008728ef0) at transactions.pb.swift:30039:23
    frame #46: 0x0000000109fb9d6f Glide`partial apply for closure #1 in Transactions_Item.decodeMessage<A>(decoder:) at <compiler-generated>:0
    frame #47: 0x0000000109db1eb2 Glide`thunk for @callee_guaranteed (@guaranteed Transactions_Item._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #48: 0x0000000109fb9d94 Glide`partial apply for thunk for @callee_guaranteed (@guaranteed Transactions_Item._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #49: 0x00007fff511478bc libswiftCore.dylib`Swift.withExtendedLifetime<A, B>(A, (A) throws -> B) throws -> B + 12
    frame #50: 0x0000000109ca8fca Glide`Transactions_Item.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700008728ef0, self=Glide.Transactions_Item @ 0x00007fd86799e098) at transactions.pb.swift:29966:9
    frame #51: 0x0000000109def5dd Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Transactions_Item at <compiler-generated>:0
    frame #52: 0x000000010cfba725 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Transactions_Item @ 0x00007fd86799e098, self=SwiftProtobuf.JSONDecoder @ 0x0000700008728ef0) at JSONDecoder.swift:514:19
    frame #53: 0x000000010cfbb084 SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x0000700008729e10) at JSONDecoder.swift:533:20
    frame #54: 0x000000010cfbf14d SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #55: 0x0000000109e1db6d Glide`closure #1 in Transactions_Item.TransactionDocument.decodeMessage<D>(_storage=0x00007fd86799de10, decoder=SwiftProtobuf.JSONDecoder @ 0x0000700008729e10) at transactions.pb.swift:31384:30
    frame #56: 0x0000000109fba1ef Glide`partial apply for closure #1 in Transactions_Item.TransactionDocument.decodeMessage<A>(decoder:) at <compiler-generated>:0
    frame #57: 0x0000000109e1ea42 Glide`thunk for @callee_guaranteed (@guaranteed Transactions_Item.TransactionDocument._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #58: 0x0000000109fba214 Glide`partial apply for thunk for @callee_guaranteed (@guaranteed Transactions_Item.TransactionDocument._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #59: 0x00007fff511478bc libswiftCore.dylib`Swift.withExtendedLifetime<A, B>(A, (A) throws -> B) throws -> B + 12
    frame #60: 0x0000000109e1d62a Glide`Transactions_Item.TransactionDocument.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700008729e10, self=Glide.Transactions_Item.TransactionDocument @ 0x00007000087570c0) at transactions.pb.swift:31378:9
    frame #61: 0x0000000109e26c6d Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Transactions_Item.TransactionDocument at <compiler-generated>:0
    frame #62: 0x000000010cfba725 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Transactions_Item.TransactionDocument @ 0x00007000087570c0, self=SwiftProtobuf.JSONDecoder @ 0x0000700008729e10) at JSONDecoder.swift:514:19
    frame #63: 0x000000010cfbb084 SwiftProtobuf`JSONDecoder.decodeSingularMessageField<M>(value=some, self=SwiftProtobuf.JSONDecoder @ 0x0000700008764de0) at JSONDecoder.swift:533:20
    frame #64: 0x000000010cfbf14d SwiftProtobuf`protocol witness for Decoder.decodeSingularMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #65: 0x0000000109cae348 Glide`closure #1 in Transactions_Item.decodeMessage<D>(_storage=0x00007fd866016800, decoder=SwiftProtobuf.JSONDecoder @ 0x0000700008764de0) at transactions.pb.swift:29983:23
    frame #66: 0x0000000109fb9d6f Glide`partial apply for closure #1 in Transactions_Item.decodeMessage<A>(decoder:) at <compiler-generated>:0
    frame #67: 0x0000000109db1eb2 Glide`thunk for @callee_guaranteed (@guaranteed Transactions_Item._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #68: 0x0000000109fb9d94 Glide`partial apply for thunk for @callee_guaranteed (@guaranteed Transactions_Item._StorageClass) -> (@error @owned Error) at <compiler-generated>:0
    frame #69: 0x00007fff511478bc libswiftCore.dylib`Swift.withExtendedLifetime<A, B>(A, (A) throws -> B) throws -> B + 12
    frame #70: 0x0000000109ca8fca Glide`Transactions_Item.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700008764de0, self=Glide.Transactions_Item @ 0x0000700008764b40) at transactions.pb.swift:29966:9
    frame #71: 0x0000000109def5dd Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Transactions_Item at <compiler-generated>:0
    frame #72: 0x000000010cfba725 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Transactions_Item @ 0x0000700008764b40, self=SwiftProtobuf.JSONDecoder @ 0x0000700008764de0) at JSONDecoder.swift:514:19
    frame #73: 0x000000010cfbba67 SwiftProtobuf`JSONDecoder.decodeRepeatedMessageField<M>(value=0 values, self=SwiftProtobuf.JSONDecoder @ 0x0000700008765610) at JSONDecoder.swift:564:24
    frame #74: 0x000000010cfbf18d SwiftProtobuf`protocol witness for Decoder.decodeRepeatedMessageField<A>(value:) in conformance JSONDecoder at <compiler-generated>:0
    frame #75: 0x0000000109fe4951 Glide`Transactions_ItemList.decodeMessage<D>(decoder=SwiftProtobuf.JSONDecoder @ 0x0000700008765610, self=Glide.Transactions_ItemList @ 0x0000700008765850) at transactions.pb.swift:40058:28
    frame #76: 0x0000000109fe5b0d Glide`protocol witness for Message.decodeMessage<A>(decoder:) in conformance Transactions_ItemList at <compiler-generated>:0
    frame #77: 0x000000010cfba725 SwiftProtobuf`JSONDecoder.decodeFullObject<M>(message=Glide.Transactions_ItemList @ 0x0000700008765850, self=SwiftProtobuf.JSONDecoder @ 0x0000700008765610) at JSONDecoder.swift:514:19
    frame #78: 0x000000010cffa9a9 SwiftProtobuf`closure #1 in Message.init(body=Swift.UnsafeRawBufferPointer @ 0x00007000087656a0, options=(messageDepthLimit = 100, ignoreUnknownFields = false), self=Glide.Transactions_ItemList @ 0x0000700008765850) at Message+JSONAdditions.swift:109:21
    frame #79: 0x000000010cffab93 SwiftProtobuf`partial apply for closure #1 in Message.init(jsonUTF8Data:options:) at <compiler-generated>:0
    frame #80: 0x000000010cec7bbf SwiftProtobuf`thunk for @callee_guaranteed (@unowned UnsafeRawBufferPointer) -> (@error @owned Error) at <compiler-generated>:0
    frame #81: 0x000000010cffabb4 SwiftProtobuf`partial apply for thunk for @callee_guaranteed (@unowned UnsafeRawBufferPointer) -> (@error @owned Error) at <compiler-generated>:0
    frame #82: 0x00007fff514e4863 libswiftFoundation.dylib`Foundation.Data.withUnsafeBytes<A>((Swift.UnsafeRawBufferPointer) throws -> A) throws -> A + 579
    frame #83: 0x000000010cffa308 SwiftProtobuf`Message.init(jsonUTF8Data=8404 bytes, options=(messageDepthLimit = 100, ignoreUnknownFields = false)) at Message+JSONAdditions.swift:95:22
    frame #84: 0x00000001092a39b7 Glide`closure #1 in AppDelegate.application(_:didFinishLaunchingWithOptions:) at AppDelegate.swift:27:64
    frame #85: 0x0000000108c032f0 Glide`thunk for @escaping @callee_guaranteed () -> () at <compiler-generated>:0
    frame #86: 0x000000010d3dff11 libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #87: 0x000000010d3e0e8e libdispatch.dylib`_dispatch_client_callout + 8
    frame #88: 0x000000010d3e32d8 libdispatch.dylib`_dispatch_queue_override_invoke + 1022
    frame #89: 0x000000010d3f2399 libdispatch.dylib`_dispatch_root_queue_drain + 351
    frame #90: 0x000000010d3f2ca6 libdispatch.dylib`_dispatch_worker_thread2 + 135
    frame #91: 0x00007fff51c089f7 libsystem_pthread.dylib`_pthread_wqthread + 220
    frame #92: 0x00007fff51c07b77 libsystem_pthread.dylib`start_wqthread + 15

I know not having a self-contained example that can trigger this makes debugging difficult. I'm working on getting that done, but in the mean time, any thoughts/ideas around where this may be coming from?

Thanks!

Lukasa commented 4 years ago

Important point to highlight is that it only crashes when the decoding is being done on a background thread. If I run it on the main thread, it just works.

That suggests a possible issue regarding threading. If you can get a run with Thread Sanitizer turned on it'd be a good idea to start there, as it's possible this is a threading issue in your code.

If not, I think the traceback is very strange. We're in the middle of a bunch of type metadata gathering for the generic call to FixedWidthInteger.init. This is a fairly unexpected place to crash, deep in the Swift runtime. If this doesn't turn out to be either a threading or memory safety issue, then this is a bug against Swift.

nanocba commented 4 years ago

Thanks @Lukasa. Enabling thread sanitiser makes the app crash on the same place I reported this issue for the first time. Does that tell anything about this issue?

On the other hand, enabling address sanitiser makes the app NOT to crash.

I doubt there's a threading issue that our code is introducing since I'm isolating the code by loading the data from a file and triggering the decoding process on app delegate's did finish launching like this:

DispatchQueue.global().async {
            do {
                let data = try Data(contentsOf: Bundle.main.url(forResource: "documents", withExtension: "json")!)
                let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String: Any]
                var decodingOptions = JSONDecodingOptions()
                decodingOptions.ignoreUnknownFields = true
                let decodedObject = try? Transactions_ItemList.init(jsonUTF8Data: JSONSerialization.data(withJSONObject: json["data"] as Any), options: decodingOptions)
                print(decodedObject)
            } catch {
                print(error)
            }
        }

I changed the above to use DispatchQueue.main then it works as expected. Also if I remove the problematic data from the JSON it also works as expected even when dispatched on a background thread.

nanocba commented 4 years ago

@Lukasa @thomasvl is there any chance I could share with you the example project privately? I don't have it ready yet, but I was just checking since this will require us to expose all of our protos and definitely don't want to do that publicly.

allevato commented 4 years ago

Important point to highlight is that it only crashes when the decoding is being done on a background thread. If I run it on the main thread, it just works.

This, combined with the amount of recursion in the backtrace, makes me think that you're hitting the stack size limit for background threads, which is much smaller than the main thread (512KB vs. 8MB). https://developer.apple.com/library/archive/qa/qa1419/_index.html

We've run into the similar problems in swift-format with very deep syntax trees. I'm not aware of any way to control the stack size of threads created by Dispatch, unfortunately; but Foundation's Thread class has a stackSize property that you can set before starting the thread.

A quick and dirty test you could try would be to have your dispatch task immediately start a Thread with the work you want to execute and then wait for that thread to complete (instead of having the dispatch task do the work directly). Start it with the default stack size of 512KB and see if it crashes the same way, then slowly grow it and see if it still crashes (but gets further in the backtrace) or eventually succeeds.

nanocba commented 4 years ago

@allevato you were spot on! stackSize = 8192 8 fails, but stackSize = 8192 9 works! One thing that I do find strange though is that I don't think our tree is that complex though:

{
  "status": 200,
  "data": {
    "data": [
      {
        "id": "654979",
        "vers": "655842",
        "transId": "654209",
        "title": "Cover Sheet.pdf",
        "can": {
          "edit": false,
          "sign": false,
          "drag": true
        },
        "opStatus": "ARCHIVED",
        "effectiveFrom": "1592948325533",
        "effectiveTo": "253402300800000",
        "createdAt": "1592924626685",
        "kind": "TRANSACTION_DOCUMENT",
        "transactionDocument": {
          "kind": "COVER_SHEET",
          "version": 2,
          "documentId": "ae254f36-9b97-4d8a-aadd-1df163411e07",
          "latestVersionId": "655202",
          "latestVersion": {
            "id": "655202",
            "vers": "655200",
            "transId": "654209",
            "title": "Cover Sheet.pdf",
            "can": {

            },
            "effectiveFrom": "1592934677203",
            "effectiveTo": "253402300800000",
            "createdAt": "1592934677203",
            "kind": "TRANSACTION_DOCUMENT_VERSION",
            "transactionDocumentVersion": {
              "source": {
                "label": "Cover Sheet.pdf",
                "kind": "COVER_SHEET",
                "coverSheet": {
                  "documentId": "ae254f36-9b97-4d8a-aadd-1df163411e07"
                }
              },
              "version": 2,
              "documentId": "ae254f36-9b97-4d8a-aadd-1df163411e07",
              "document": {
                "intId": "6353",
                "url": "https://staging.glide.com/transactions/654209/cover_sheet/732a2dff-0b60-44c2-a83d-018bead56d28/655200",
                "externalUrl": "https://staging.glide.com/transactions/654209/cover_sheet/732a2dff-0b60-44c2-a83d-018bead56d28/655200",
                "isExternal": true,
                "filename": "Cover Sheet.pdf",
                "byteSize": "10000",
                "id": "ae254f36-9b97-4d8a-aadd-1df163411e07",
                "updatedAt": "1592934676056",
                "createdAt": "1592934676056",
                "analysis": {
                  "id": "3935",
                  "analysisVersion": "1",
                  "documentResult": {
                    "pageCount": 2,
                    "hexdigest": "f20c81034861c4b710e1479a9c8393c8"
                  },
                  "thumbnailUrl": "https://s3-us-west-1.amazonaws.com/devretitle/documents/BcYy4NbkuzZPVtv9-SFgUhm7qGu591yIqRcMoBq2gq0/thumbnail",
                  "stateByPart": {
                    "1": {
                      "status": "COMPLETE",
                      "attemptedAt": "1592934740434",
                      "finishedAt": "1592934741688"
                    },
                    "2": {
                      "status": "COMPLETE",
                      "attemptedAt": "1592934740434",
                      "finishedAt": "1592934749539"
                    },
                    "3": {
                      "status": "COMPLETE",
                      "attemptedAt": "1592934740434",
                      "finishedAt": "1592934749539"
                    },
                    "4": {
                      "status": "COMPLETE",
                      "attemptedAt": "1592934740434",
                      "finishedAt": "1592934743582"
                    }
                  },
                  "updatedAt": "1592934749541",
                  "createdAt": "1592934676056"
                }
              },
              "url": "https://staging.glide.com/transactions/654209/cover_sheet/732a2dff-0b60-44c2-a83d-018bead56d28/655200"
            },
            "inEdges": [
              {
                "kind": "TD_HAS_TDV",
                "item1Id": "654979",
                "item2Id": "655202",
                "createdAt": "1592934676855"
              }
            ],
            "outEdges": [

            ]
          },
          "archived": true,
          "index": 0,
          "lastActiveFolderId": "654234"
        },
        "inEdges": [

        ],
        "outEdges": [
          {
            "kind": "TD_HAS_TDV",
            "item1Id": "654979",
            "item2Id": "654980",
            "createdAt": "1592924626320"
          },
          {
            "kind": "TD_HAS_TDV",
            "item1Id": "654979",
            "item2Id": "655202",
            "createdAt": "1592934676855"
          }
        ]
      },
      {
        "id": "654976",
        "vers": "654983",
        "transId": "654209",
        "title": "tcl_renuncia.pdf",
        "can": {
          "edit": true,
          "sign": true,
          "drag": true
        },
        "opStatus": "NON_EMPTY",
        "effectiveFrom": "1592924801633",
        "effectiveTo": "253402300800000",
        "createdAt": "1592924626685",
        "kind": "TRANSACTION_DOCUMENT",
        "transactionDocument": {
          "version": 1,
          "updatedAt": "1592924626685",
          "documentId": "17165559-ae04-489e-87a9-ef559ffa6d64",
          "latestVersionId": "654977",
          "latestVersion": {
            "id": "654977",
            "vers": "654975",
            "transId": "654209",
            "title": "tcl_renuncia.pdf",
            "can": {

            },
            "effectiveFrom": "1592924626685",
            "effectiveTo": "253402300800000",
            "createdAt": "1592924626685",
            "kind": "TRANSACTION_DOCUMENT_VERSION",
            "transactionDocumentVersion": {
              "source": {
                "kind": "UPLOAD",
                "upload": {
                  "url": "https://s3.us-west-1.amazonaws.com/devretitle/e63ff0fe213de66b6b000469/tcl_renuncia.pdf",
                  "filename": "tcl_renuncia.pdf",
                  "byteSize": "134510"
                }
              },
              "version": 1,
              "documentId": "17165559-ae04-489e-87a9-ef559ffa6d64",
              "document": {
                "intId": "6350",
                "url": "https://s3.us-west-1.amazonaws.com/devretitle/e63ff0fe213de66b6b000469/tcl_renuncia.pdf",
                "externalUrl": "https://s3.us-west-1.amazonaws.com/devretitle/e63ff0fe213de66b6b000469/tcl_renuncia.pdf",
                "isExternal": true,
                "filename": "tcl_renuncia.pdf",
                "byteSize": "134510",
                "id": "17165559-ae04-489e-87a9-ef559ffa6d64",
                "updatedAt": "1592924625744",
                "createdAt": "1592924625744",
                "analysis": {
                  "id": "3933",
                  "analysisVersion": "1",
                  "documentResult": {
                    "pageCount": 1,
                    "hexdigest": "89ea9626c3af2dedad1771ed451dc572"
                  },
                  "thumbnailUrl": "https://s3-us-west-1.amazonaws.com/devretitle/documents/SAHbEbOed-oF-EIExt7yM-TAdNKCBloY4ckMuSycVR8/thumbnail",
                  "stateByPart": {
                    "1": {
                      "status": "COMPLETE",
                      "attemptedAt": "1592924626783",
                      "finishedAt": "1592924627812"
                    },
                    "2": {
                      "status": "COMPLETE",
                      "attemptedAt": "1592924626783",
                      "finishedAt": "1592924636517"
                    },
                    "3": {
                      "status": "COMPLETE",
                      "attemptedAt": "1592924626783",
                      "finishedAt": "1592924636517"
                    },
                    "4": {
                      "status": "COMPLETE",
                      "attemptedAt": "1592924626783",
                      "finishedAt": "1592924629238"
                    }
                  },
                  "updatedAt": "1592924636519",
                  "createdAt": "1592924626778"
                }
              },
              "url": "https://s3.us-west-1.amazonaws.com/devretitle/e63ff0fe213de66b6b000469/tcl_renuncia.pdf"
            },
            "inEdges": [
              {
                "kind": "TD_HAS_TDV",
                "item1Id": "654976",
                "item2Id": "654977",
                "createdAt": "1592924626166"
              }
            ],
            "outEdges": [

            ]
          },
          "index": 1,
          "usersSeen": [
            {
              "userId": "10523",
              "versionId": "654977",
              "timestamp": "1592924801621"
            }
          ]
        },
        "inEdges": [
          {
            "kind": "FOLDER_HAS_DOCUMENT",
            "item1Id": "654234",
            "item2Id": "654976",
            "createdAt": "1592924625832"
          }
        ],
        "outEdges": [
          {
            "kind": "TD_HAS_TDV",
            "item1Id": "654976",
            "item2Id": "654977",
            "createdAt": "1592924626166"
          }
        ]
      }
    ],
    "total": 0,
    "hasMore": true
  }
}

May that be a sign that something else is going on?

nanocba commented 4 years ago

Btw I have the project where this is isolated ready to be shared. I just would like a way to share it privately so our protos aren't exposed publicly. Would you be able to take a look at it?

thomasvl commented 4 years ago

Since this seems to be the Swift runtime and stack usage thing, it likely makes sense to open a Swift bug. I think you can also open a feedback with Apple and post your code to that so it remains private (just have the public issue reference the feedback number to help Apple folks connect the dots).

tbkka commented 4 years ago

Just to clarify one detail: I presume this is in a debug build? Does it still crash in a release (optimized) build?

(I would expect a release build to optimize away some of the generic operations that are getting invoked here. I suspect that this would result in an optimized build requiring less stack space in this particular case.)

thomasvl commented 4 years ago

Once you do file a feedback and/or open a Swift issue, please link it here so it can be referenced if needed. Thanks.

thomasvl commented 4 years ago

@nanocba can you try testing again with current HEAD to see if the other changes we made for #1034 also helped your problem case?

thomasvl commented 3 years ago

@nanocba have you gotten a chance to see if the mentioned changes help your case out?