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

AHC causes uncleanShutdown error on server side. #808

Open
toffaletti opened this issue Feb 7, 2025 · 3 comments
Open

AHC causes uncleanShutdown error on server side. #808

toffaletti opened this issue Feb 7, 2025 · 3 comments

Comments

@toffaletti
Copy link

I have a server that is functionally similar in setup to hummingbird-examples/http2, when I use async-http-client to make a request with a command line program that exits after the request, humming bird reports this error:

[HummingbirdHTTP2] Error handling inbound connection for HTTP2 handler: uncleanShutdown

I do not see the same error when using curl:

curl --cacert certs/ca.crt --http2 -v https://localhost:8043/healthcheck
    var tlsConfiguration: TLSConfiguration {
        get throws {
            let certificateChain = try NIOSSLCertificate.fromPEMFile(self.certificateChain)
            var tlsConfiguration = TLSConfiguration.makeClientConfiguration()
            tlsConfiguration.trustRoots = .certificates(certificateChain)
            #if os(macOS)
            tlsConfiguration.certificateVerification = .none
            #else
            // not supported with Network.framework
            tlsConfiguration.certificateVerification = .noHostnameVerification
            #endif
            return tlsConfiguration
        }
    }

relevant code in the run() async throws method of an AsyncParsableCommand:

        var clientConfig = HTTPClient.Configuration()
        clientConfig.tlsConfiguration = try self.tlsConfiguration
        try await HTTPClient.withHTTPClient(configuration: clientConfig) { client in
            var request = HTTPClientRequest(url: url.absoluteString)
            request.method = .POST
            request.headers.add(name: "content-type", value: "application/json")
            request.headers.add(name: "content-length", value: "\(payloadData.count)")
            request.body = .bytes(payloadData)
            let response = try await client.execute(request, timeout: .seconds(30))
            let body = try await response.body.collect(upTo: 10 * 1024 * 1024)
        }

I've tried many variations that all execute await client.shutdown() before exiting and they all result in this error. From what Cory says here: https://forums.swift.org/t/niossl-spurious-uncleanshutdown-error/53031/3 it seems like AHC isn't sending CLOSE_NOTIFY on shutdown?

@Lukasa
Copy link
Collaborator

Lukasa commented Feb 10, 2025

That seems possible, if unfortunate. Generally it won't matter for HTTP (as discussed in the linked thread), but it's definitely rude.

I suspect this only happens using the swift-nio-transport-services backend. Have you tried this with the client on Linux?

@toffaletti
Copy link
Author

You're right, I can't reproduce it using Linux as the client.

@Lukasa
Copy link
Collaborator

Lukasa commented Feb 12, 2025

Great, ok. So I think this is a problem with shutdown in the NIOTS backend, which does not auto-promote the shutdown to half-closure. I think if we explicitly performed half-closure everywhere, this would resolve matters.

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

No branches or pull requests

2 participants