How to further debug a simple HTTP request?

So the stalls have disappeared, but now that my program has evolved a bit, I am sometimes, near the very beginning of execution, getting a crash. It either crashes very shortly after startup, or it doesn’t crash. Does this stack trace ring any bells with anyone?

0x00007fffe3f289e5 in $s10Foundation6LocaleV9referenceAcA8NSLocaleC_tcfC () from /usr/lib/swift/linux/libFoundation.so
(gdb) bt
#0 0x00007fffe3f289e5 in $s10Foundation6LocaleV9referenceAcA8NSLocaleC_tcfC ()
at /usr/lib/swift/linux/libFoundation.so
#1 0x00007fffe44b9aec in $s20FoundationNetworking16_HTTPURLProtocolC19configureEasyHandle3for4bodyyAA10URLRequestV_AA14URLSessionTaskC5_BodyOtF () at /usr/lib/swift/linux/libFoundationNetworking.so
#2 0x00007fffe44c6e43 in $s20FoundationNetworking15_NativeProtocolC16startNewTransfer4withyAA10URLRequestV_tFyAA14URLSessionTaskC5_BodyOcfU_TA () at /usr/lib/swift/linux/libFoundationNetworking.so
#3 0x00007fffe44d6e17 in $s20FoundationNetworking14URLSessionTaskC7getBody10completionyyAC01_F0Oc_tF ()
at /usr/lib/swift/linux/libFoundationNetworking.so
#4 0x00007fffe44c4041 in $s20FoundationNetworking15_NativeProtocolC16startNewTransfer4withyAA10URLRequestV_tF ()
at /usr/lib/swift/linux/libFoundationNetworking.so
#5 0x00007fffe44c433a in $s20FoundationNetworking15_NativeProtocolC6resumeyyF ()
at /usr/lib/swift/linux/libFoundationNetworking.so
#6 0x00007fffe44e1d67 in $s20FoundationNetworking14URLSessionTaskC6resumeyyFyyXEfU_yAA11URLProtocolCSgcfU_yycfU_TA ()
at /usr/lib/swift/linux/libFoundationNetworking.so

Sorry, I can't really help here as I've never really used swift-corelibs-foundation other than to ensure Alamofire builds with it. You can try AsyncHTTPClient which using SwiftNIO under the hood, if you don't mind separate code paths on Linux and Apple.

I tried to package build Alamofire on linux (in my docker container) and it so many c++ compiler errors (probably in SwiftNIO) that i crossed it off the list in the first two minutes…

I’m about to try just writing a simple C++ wrapper around libcurl because this is so simple, and jump to that instead, because my API (which is old-ish) is already setup to treat HTTP calls as blocking (i.e. running from another thread which then delivers via callback/dispatch as needed).

You mean AsyncHTTPClient? Alamofire depends on FoundationNetworking on Linux, so if you can build swift-corelibs-foundation, Alamofire is just a Swift layer on top.

Like I said, swift-corelibs-foundation is so feature limited I haven't bothered to port Alamofire's test suite, so I can't vouch for its performance or stability at all.

The backtrace demangles as:

#0 0x00007fffe3f289e5 in $Foundation.Locale.init(reference: Foundation.NSLocale) -> Foundation.Locale () at /usr/lib/swift/linux/libFoundation.so
#1 0x00007fffe44b9aec in $FoundationNetworking._HTTPURLProtocol.configureEasyHandle(for: FoundationNetworking.URLRequest, body: FoundationNetworking.URLSessionTask._Body) -> () at /usr/lib/swift/linux/libFoundationNetworking.so
...

other than that - no idea.

I can't see where configureEasyHandle even accesses a locale, but perhaps something got inlined away. In any case, all I can think of is that NSLocale failed to load something from the system, since NSLocale.system is one of the few accesses I see in that file.

Consider serializing execution on a single URLSession subclass (untested!)
typealias URLDataTaskCallback = (Data?, URLResponse?, Error?) -> Void

class SerializedURLSession: URLSession {
    private var serialQueue = DispatchQueue(label: "SerializedURLSessionQueue")
    private var requests: [(URLRequest, URLDataTaskCallback)] = []
    private var busy = false
    
    func resumedDataTask(with request: URLRequest, completionHandler: @escaping URLDataTaskCallback) {
        serialQueue.async { [self] in
            requests.append((request, completionHandler))
            processRequestQueue()
        }
    }

    func resumedDataTask(with url: URL, completionHandler: @escaping URLDataTaskCallback) {
        resumedDataTask(with: URLRequest(url: url), completionHandler: completionHandler)
    }
    
    private func processRequestQueue() {
        if busy || requests.isEmpty { return }
        busy = true
        let (request, callback) = requests.removeFirst()
        dataTask(with: request) { [self] data, response, error in
            delegateQueue.addOperation {
                callback(data, response, error)
            }
            serialQueue.async {
                busy = false
                processRequestQueue()
            }
        }.resume()
    }
}

Note the API is slightly difference in that it doesn't return the data task.

Perhaps way too slow for real usage (executing one request at a time, the next request is scheduled only after the first one completes, everything is executed on a single serial queue), but should at least fix the crash.

But I don’t build the core lib you mentioned, it is prebuilt in my docker image. It’s too difficult for me to set up a Linux mach8ne that can build the toolchain here at work.

What Linux image are you using? I test Alamofire building on Swift 5.6.1 Ubuntu, as well as the nightly Swift compiler. And yeah, Foundation is included with Swift on Linux. So there shouldn't be any C++ building for Alamofire, just Swift.

Centos. At Pixar my Linux is redhat7.

I am pretty sure I tried to build swiftNIO to avoid FoundationNetworking which I assume at this point just slightly buggy. It’s a shame because it is so close to working perfectly for me.

Are you building a Swift package? NIO's pretty well tested when integrated on the official Swift Linux images. In fact, any Swift package using NIO should also build on macOS, so you could test on macOS first, knowing that the code should be essentially the same on Linux.

I just did a quick test build on the Swift centOS image and it worked fine: Build All Swift-Supported Linux Distributions · Alamofire/Alamofire@cddd541 · GitHub

I’ll try the async http client again (i only build with swift package manager) and see what i get.
I assumed the tools in my docker image weren’t up to snuff.

I suggest composing on top of the official Swift images to ensure you have a working toolchain.

See Apple Developer Documentation.