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

Segmentation fault 11 on codegen #3445

Closed
Almaz5200 opened this issue Sep 23, 2024 · 10 comments
Closed

Segmentation fault 11 on codegen #3445

Almaz5200 opened this issue Sep 23, 2024 · 10 comments
Labels

Comments

@Almaz5200
Copy link
Contributor

Summary

I’m experiencing a runtime crash when using Apollo codegen with Xcode 16 in Swift 5 language mode. The project compiles successfully, but upon running, it crashes with a “Segmentation fault: 11” error. When debugging, the crash points to line 15 in Collection+ConcurrentCompactMap.swift.

Version

1.15.1

Steps to reproduce the behavior

1.	Use Apollo codegen in a project with Xcode 16 and Swift 5 language mode.
2.	Compile the project (compiles without errors).
3.	Run the application.
4.	Encounter the runtime crash with “Segmentation fault: 11”.

Logs

Thread 1 Queue : com.apple.main-thread (serial)
#0	0x000000019ab63e34 in mach_msg2_trap ()
#1	0x000000019ab765d0 in mach_msg2_internal ()
#2	0x000000019ab6c9d8 in mach_msg_overwrite ()
#3	0x000000019ab6417c in mach_msg ()
#4	0x000000019ac8e73c in __CFRunLoopServiceMachPort ()
#5	0x000000019ac8cfec in __CFRunLoopRun ()
#6	0x000000019ac8c4b4 in CFRunLoopRunSpecific ()
#7	0x000000019ad0737c in CFRunLoopRun ()
#8	0x0000000274452dc4 in swift_task_asyncMainDrainQueueImpl ()
#9	0x0000000274452d84 in swift_task_asyncMainDrainQueue ()
#10	0x00000001000053dc in main ()
#11	0x000000019a823274 in start ()
Thread 2#0	0x0000000100aacce8 in start_wqthread ()
JavaScriptCore libpas scavenger (3)#0	0x000000019ab675cc in __psynch_cvwait ()
#1	0x0000000100aa6fc0 in _pthread_cond_wait ()
#2	0x00000001ba5cbb7c in scavenger_thread_main ()
#3	0x0000000100aa29ac in _pthread_start ()
Thread 4 Queue : com.apple.root.default-qos.cooperative (concurrent)
#0	0x000000010019b79c in withThrowingTaskGroup<τ_0_0, τ_0_1>(of:returning:isolation:body:) ()
#1	0x0000000100199f2c in Collection.concurrentCompactMap<OrderedCollections.OrderedSet<String>>(_:) at /Users/almaz5200/Library/Developer/Xcode/DerivedData/ApolloCodegen-atnkdqhvebnanxgbiafqqdikldql/SourcePackages/checkouts/apollo-ios-codegen/Sources/Utilities/Collection+ConcurrentCompactMap.swift:15
#2	0x00000001000125c0 in ApolloCodegen.createSchema(_:) at /Users/almaz5200/Library/Developer/Xcode/DerivedData/ApolloCodegen-atnkdqhvebnanxgbiafqqdikldql/SourcePackages/checkouts/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift:210
#3	0x0000000100011688 in implicit closure #1 in ApolloCodegen.compileGraphQLResult() at /Users/almaz5200/Library/Developer/Xcode/DerivedData/ApolloCodegen-atnkdqhvebnanxgbiafqqdikldql/SourcePackages/checkouts/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift:167
#4	0x0000000100011848 in partial apply for implicit closure #1 in ApolloCodegen.compileGraphQLResult() ()
Thread 5 Queue : com.apple.root.default-qos.cooperative (concurrent)
#0	0x000000019ab67574 in getattrlistbulk ()
#1	0x000000019e5d124c in NextEntryFromParent ()
#2	0x000000019e5d0fdc in DirEnumRead ()
#3	0x000000019e5d09e8 in _GetDirectoryURLs ()
#4	0x000000019e5cf5a8 in _URLEnumeratorGetNextURL ()
#5	0x000000019be95530 in -[NSURLDirectoryEnumerator nextObject] ()
#6	0x000000019ac663fc in -[NSEnumerator countByEnumeratingWithState:objects:count:] ()
#7	0x000000019c32de2c in Foundation.NSFastEnumerationIterator.next() -> Swift.Optional<Any> ()
#8	0x000000010009120c in Glob.expand(_:excludingDirectories:) at /Users/almaz5200/Library/Developer/Xcode/DerivedData/ApolloCodegen-atnkdqhvebnanxgbiafqqdikldql/SourcePackages/checkouts/apollo-ios-codegen/Sources/ApolloCodegenLib/Glob.swift:176
#9	0x000000010008ff80 in Glob.expand(_:excludingDirectories:) at /Users/almaz5200/Library/Developer/Xcode/DerivedData/ApolloCodegen-atnkdqhvebnanxgbiafqqdikldql/SourcePackages/checkouts/apollo-ios-codegen/Sources/ApolloCodegenLib/Glob.swift:111
#10	0x000000010008f764 in Glob.match(excludingDirectories:) at /Users/almaz5200/Library/Developer/Xcode/DerivedData/ApolloCodegen-atnkdqhvebnanxgbiafqqdikldql/SourcePackages/checkouts/apollo-ios-codegen/Sources/ApolloCodegenLib/Glob.swift:74
#11	0x0000000100012b30 in static ApolloCodegen.match(searchPaths:relativeTo:) at /Users/almaz5200/Library/Developer/Xcode/DerivedData/ApolloCodegen-atnkdqhvebnanxgbiafqqdikldql/SourcePackages/checkouts/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift:242
#12	0x0000000100013298 in ApolloCodegen.createOperationsDocument(_:) at /Users/almaz5200/Library/Developer/Xcode/DerivedData/ApolloCodegen-atnkdqhvebnanxgbiafqqdikldql/SourcePackages/checkouts/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift:220
#13	0x00000001000119bc in implicit closure #2 in ApolloCodegen.compileGraphQLResult() at /Users/almaz5200/Library/Developer/Xcode/DerivedData/ApolloCodegen-atnkdqhvebnanxgbiafqqdikldql/SourcePackages/checkouts/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift:168
#14	0x0000000100011b7c in partial apply for implicit closure #2 in ApolloCodegen.compileGraphQLResult() ()

Anything else?

Here's our full script:

@available(macOS 10.15, macCatalyst 13, iOS 13, tvOS 13, watchOS 6, *)
struct SwiftScript: ParsableCommand {

    static let configuration = CommandConfiguration(
        abstract: """
            A swift-based utility for performing Apollo-related tasks.

            NOTE: If running from a compiled binary, prefix subcommands with `swift-script`. Otherwise use `swift run ApolloCodegen [subcommand]`.
            """,
        subcommands: [DownloadSchema.self, GenerateCode.self])

    /// The URL to the source root for your main project.
    /// Defaults to the folder containing the `ApolloCodgen` Package folder.
    ///
    /// NOTE: - You may need to change this if your project has a different structure
    /// than the suggested structure.
    static let SourceRootURL: URL = {
        let parentFolderOfScriptFile = URL(string: FileManager.default.currentDirectoryPath)!
        let sourceRootURL =
            parentFolderOfScriptFile
            .parentFolderURL()  // Result: Project source root folder
        CodegenLogger.log("Source Root URL: \(sourceRootURL)")
        return sourceRootURL
    }()

    // The URL where the downloaded schema will be written to.
    // The default writes the schema to your project's root.
    static let SchemaOutputURL: URL = {
        SourceRootURL
            .appendingPathComponent("NetworkCore")
            .appendingPathComponent("Sources")
            .appendingPathComponent("NetworkService")
            .appendingPathComponent("Generated")
            .appendingPathComponent("schema.graphqls")
    }()

    /// The sub-command to download a schema from a provided endpoint.
    struct DownloadSchema: AsyncParsableCommand {
        static let configuration = CommandConfiguration(
            commandName: "downloadSchema",
            abstract:
                "Downloads the schema with the settings you've set up in the `DownloadSchema` command in `main.swift`."
        )

        mutating func run() async throws {
            // Set up the URL you want to use to download the project
            let endpoint = URL(string: "*our url*")!

            // Make sure the folder is created before trying to download something to it.
            let folderForDownloadedSchema = SchemaOutputURL.deletingLastPathComponent()

            // Create a configuration object for downloading the schema.
            // Provided code will download the schema via an introspection query to the provided URL as
            // SDL (GraphQL Schema Definition Language).
            // For all configuration parameters see:
            // https://www.apollographql.com/docs/ios/api/ApolloCodegenLib/structs/ApolloSchemaDownloadConfiguration/
            let schemaDownloadOptions = ApolloSchemaDownloadConfiguration(
                using: .introspection(endpointURL: endpoint),
                outputPath: SchemaOutputURL.path
            )

            // Actually attempt to download the schema.
            try await ApolloSchemaDownloader.fetch(configuration: schemaDownloadOptions)
        }
    }

    /// The sub-command to actually generate code.
    struct GenerateCode: AsyncParsableCommand {
        static let configuration = CommandConfiguration(
            commandName: "generate",
            abstract:
                "Generates swift code from your schema + your operations based on information set up in the `GenerateCode` command."
        )

        mutating func run() async throws {
            /// The root of the target for which you want to generate code.
            let targetSchemaTypesURL =
                SourceRootURL
                .childFolderURL(folderName: "NetworkCore/Sources/APITypes/Generated")
            let targetRootURL =
                SourceRootURL
                .childFolderURL(folderName: "NetworkCore/Sources/NetworkService/Generated")

            /// The name of the module that will contain your generated schema objects.
            let generatedSchemaModuleName: String = "APITypes"

            // Make sure the folders exists before trying to generate code.

            // Create the Codegen configuration object. For all configuration parameters see: https://www.apollographql.com/docs/ios/api/ApolloCodegenLib/structs/ApolloCodegenConfiguration/
            let codegenConfiguration = ApolloCodegenConfiguration(
                schemaNamespace: generatedSchemaModuleName,
                input: ApolloCodegenConfiguration.FileInput(
                    schemaPath: SchemaOutputURL.path,
                    operationSearchPaths: [
                        "\(SourceRootURL.path)/DataMonolith/Sources/**/*.graphql",
                        "\(SourceRootURL.path)/NetworkCore/Sources/**/*.graphql",
                    ]),
                output: ApolloCodegenConfiguration.FileOutput(
                    schemaTypes: ApolloCodegenConfiguration.SchemaTypesFileOutput(
                        path: targetSchemaTypesURL.path,
                        moduleType: .swiftPackageManager
                    ),
                    operations: .relative(subpath: "../Generated/Operations/")
                )
            )

            // Actually attempt to generate code.
            try await ApolloCodegen.build(with: codegenConfiguration)
        }
    }

}
@Almaz5200 Almaz5200 added bug Generally incorrect behavior needs investigation labels Sep 23, 2024
@calvincestari
Copy link
Member

Thanks for reporting the issue @Almaz5200. Unfortunately there isn't enough information here to determine the cause. I also cannot replicate the error in our test projects.

If you can supply a standalone project that fails in the same way it would definitely help to debug the issue. If you have the full Xcode build log that may help too.

@Almaz5200
Copy link
Contributor Author

Thank you for a quick response @calvincestari. I was able to come up with a simple project that replicates the issue: https://github.com/Almaz5200/ApolloSegFault
You should be able to just cd into ApolloCodegen and use swift run there, see screenshot bellow

Screenshot 2024-09-23 at 8 19 14 PM

Also note, that for demonstration purposes I've hardcoded project root path, so you'll have to change it in order to run it

@Almaz5200
Copy link
Contributor Author

If you’re unable to reproduce the issue, please let me know, and I’ll gladly share build logs and any other information you may need.

@calvincestari
Copy link
Member

That project isn't failing for me @Almaz5200. There are some oddities in the output but I can get the generated operation as below:

// @generated
// This file was automatically generated and should not be edited.

@_exported import ApolloAPI
import APITypes

public class TestQQuery: GraphQLQuery {
  public static let operationName: String = "TestQ"
  public static let operationDocument: ApolloAPI.OperationDocument = .init(
    definition: .init(
      #"query TestQ { sectionQueries }"#
    ))

  public init() {}

  public struct Data: APITypes.SelectionSet {
    public let __data: DataDict
    public init(_dataDict: DataDict) { __data = _dataDict }

    public static var __parentType: any ApolloAPI.ParentType { APITypes.Objects.Query }
    public static var __selections: [ApolloAPI.Selection] { [
      .field("sectionQueries", String.self),
    ] }

    public var sectionQueries: String { __data["sectionQueries"] }
  }
}

Which version of Xcode are you using?

@Almaz5200
Copy link
Contributor Author

I've tried it with Xcode 15.4 and 16.0. It works fine on 15.4 and fails on 16.0
Regarding oddities in the output, I wouldn't read into that too much, I've made this scheme in a rush to be barely valid just for a demonstration, so there may be something wrong with it. In my case however it doesn't seem to even get to validating scheme or parsing it in any way

@calvincestari
Copy link
Member

I've tried it with Xcode 15.4 and 16.0. It works fine on 15.4 and fails on 16.0

Are you using the latest Xcode 16.0 release, build 16A242d? If you want to send me the Xcode build log I'll take a look at to see if I can glean anything else from that.

@Almaz5200
Copy link
Contributor Author

Are you using the latest Xcode 16.0 release, build 16A242d?

Yes, I do. However I also use a pre-release macOS version, which may affect something, I'll try it on another device.
See attachment bellow for build log

Build OurApolloCodegen_2024-09-24T08-45-37.txt

@Almaz5200
Copy link
Contributor Author

I've tried to replicate the issue on another machine on both macOS Sonoma and macOS Sequoia (release version) with Xcode 16.0 release, and can confirm that it worked fine in all cases.
While it still affects my work on my main machine, I believe an issue is much less critical as I've initially thought

@calvincestari
Copy link
Member

I've tried to replicate the issue on another machine on both macOS Sonoma and macOS Sequoia (release version) with Xcode 16.0 release, and can confirm that it worked fine in all cases.

Thanks for digging into this further @Almaz5200. It seems that there isn't anything we can debug further though; the Xcode build log isn't helping unfortunately.

Given this update I'm inclined to close this issue unless you can replicate it on more than one machine. If you do get to that state then we'd be happy to take another look and try resolve it.

@calvincestari calvincestari closed this as not planned Won't fix, can't repro, duplicate, stale Sep 24, 2024
Copy link
Contributor

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo iOS usage and allow us to serve you better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants