onevcat / Kingfisher

A lightweight, pure-Swift library for downloading and caching images from the web.
MIT License
23.43k stars 2.66k forks source link

crash about retrieve Image (maybe) #2183

Open bugaco opened 11 months ago

bugaco commented 11 months ago

Check List

Thanks for considering to open an issue. Before you submit your issue, please confirm these boxes are checked.

Issue Description

What

Hey, God Miao🐱 I got a crash report on Google Crashlytics. I am not sure what caused it. Are there any ideas?😯

Stack trace
# Crashlytics - Stack trace
# Platform: apple
# Date: Mon Dec 18 2023 09:31:34 GMT+0800 (China Standard Time)

Crashed: com.apple.main-thread
0  MyApp                0x39884 closure #1 in PhotoListViewController.startDownloadImage(_:) + 30 (PhotoListViewController+ImageDownload.swift:30)
1  Kingfisher                     0xda28 specialized CallbackQueue.execute(_:) + 502 (ImageCache.swift:502)
2  Kingfisher                     0x2b08c ImageCache.retrieveImage(forKey:options:callbackQueue:completionHandler:) + 501 (ImageCache.swift:501)
3  Kingfisher                     0x2b760 ImageCache.retrieveImage(forKey:options:callbackQueue:completionHandler:) + 563 (ImageCache.swift:563)
4  MyApp                0x392bc PhotoListViewController.startDownloadImage(_:) + 23 (PhotoListViewController+ImageDownload.swift:23)
5  MyApp                0xf9f8c closure #1 in PhotoListViewController.fetchData() + 45 (PhotoListViewController.swift:45)
6  MyApp                0xfbb88 partial apply for thunk for @escaping @callee_guaranteed (@guaranteed ListingDetailModel?, @guaranteed MoyaError?) -> () + 4332551048 (<compiler-generated>:4332551048)
7  MyApp                0x13f644 specialized closure #1 in MoyaProvider.requestJsonableModel<A>(target:modelType:extraPath:completion:) + 4332828228
8  MyApp                0x13f30c specialized closure #1 in MoyaProvider.requestJsonableModel<A>(target:modelType:extraPath:completion:) + 4332827404
9  Moya                           0x10914 closure #1 in MoyaProvider.requestNormal(_:callbackQueue:progress:completion:) + 288
10 Moya                           0x11280 closure #1 in closure #2 in MoyaProvider.requestNormal(_:callbackQueue:progress:completion:) + 312
11 Moya                           0x13f78 closure #2 in MoyaProvider.sendAlamofireRequest<A>(_:target:callbackQueue:progress:completion:) + 604
12 Moya                           0x15000 partial apply for closure #2 in MoyaProvider.sendAlamofireRequest<A>(_:target:callbackQueue:progress:completion:) + 120 (<compiler-generated>:120)
13 Moya                           0xc954 closure #1 in DataRequest.response(callbackQueue:completionHandler:) + 344
14 Moya                           0xd24c partial apply for closure #2 in DataRequest.response(callbackQueue:completionHandler:) + 16 (<compiler-generated>:16)
15 Alamofire                      0xa8568 partial apply for specialized closure #2 in closure #2 in closure #3 in closure #1 in DownloadRequest._response<A>(queue:responseSerializer:completionHandler:) + 48
16 Alamofire                      0x3faa0 thunk for @escaping @callee_guaranteed @Sendable () -> () + 28 (<compiler-generated>:28)
17 libdispatch.dylib              0x26a8 _dispatch_call_block_and_release + 32
18 libdispatch.dylib              0x4300 _dispatch_client_callout + 20
19 libdispatch.dylib              0x12998 _dispatch_main_queue_drain + 984
20 libdispatch.dylib              0x125b0 _dispatch_main_queue_callback_4CF + 44
21 CoreFoundation                 0x3701c __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
22 CoreFoundation                 0x33d28 __CFRunLoopRun + 1996
23 CoreFoundation                 0x33478 CFRunLoopRunSpecific + 608
24 GraphicsServices               0x34f8 GSEventRunModal + 164
25 UIKitCore                      0x22c62c -[UIApplication _run] + 888
26 UIKitCore                      0x22bc68 UIApplicationMain + 340
27 UIKitCore                      0x4563d0 __swift_destroy_boxed_opaque_existential_1Tm + 12220
28 MyApp                0x4207c main + 4331790460 (AppDelegate.swift:4331790460)
29 ???                            0x1d0322dcc (Missing)

Thread
0  libsystem_kernel.dylib         0x96d0 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x19b0 _pthread_wqthread + 364
2  libsystem_pthread.dylib        0x1a04 start_wqthread + 8

Thread
0  libsystem_pthread.dylib        0x19fc start_wqthread + 438

com.apple.uikit.eventfetch-thread
0  libsystem_kernel.dylib         0x1178 mach_msg2_trap + 8
1  libsystem_kernel.dylib         0xf10 mach_msg2_internal + 80
2  libsystem_kernel.dylib         0xe28 mach_msg_overwrite + 436
3  libsystem_kernel.dylib         0xc68 mach_msg + 24
4  CoreFoundation                 0x35b1c __CFRunLoopServiceMachPort + 160
5  CoreFoundation                 0x33a14 __CFRunLoopRun + 1208
6  CoreFoundation                 0x33478 CFRunLoopRunSpecific + 608
7  Foundation                     0x2c48c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
8  Foundation                     0x5974c -[NSRunLoop(NSRunLoop) runUntilDate:] + 64
9  UIKitCore                      0x18e4a8 -[UIEventFetcher threadMain] + 420
10 Foundation                     0xafde0 __NSThread__start__ + 732
11 libsystem_pthread.dylib        0x24d4 _pthread_start + 136
12 libsystem_pthread.dylib        0x1a10 thread_start + 8

Thread
0  libsystem_kernel.dylib         0x96d0 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x19b0 _pthread_wqthread + 364
2  libsystem_pthread.dylib        0x1a04 start_wqthread + 8

com.google.firebase.crashlytics.MachExceptionServer
0  FirebaseCrashlytics            0x21794 FIRCLSProcessRecordAllThreads + 184
1  FirebaseCrashlytics            0x21b74 FIRCLSProcessRecordAllThreads + 1176
2  FirebaseCrashlytics            0x18c24 FIRCLSHandler + 48
3  FirebaseCrashlytics            0x1b4a8 FIRCLSMachExceptionServer + 688
4  libsystem_pthread.dylib        0x24d4 _pthread_start + 136
5  libsystem_pthread.dylib        0x1a10 thread_start + 8

com.apple.NSURLConnectionLoader
0  libsystem_kernel.dylib         0x1178 mach_msg2_trap + 8
1  libsystem_kernel.dylib         0xf10 mach_msg2_internal + 80
2  libsystem_kernel.dylib         0xe28 mach_msg_overwrite + 436
3  libsystem_kernel.dylib         0xc68 mach_msg + 24
4  CoreFoundation                 0x35b1c __CFRunLoopServiceMachPort + 160
5  CoreFoundation                 0x33a14 __CFRunLoopRun + 1208
6  CoreFoundation                 0x33478 CFRunLoopRunSpecific + 608
7  CFNetwork                      0x25a060 estimatedPropertyListSize + 38188
8  Foundation                     0xafde0 __NSThread__start__ + 732
9  libsystem_pthread.dylib        0x24d4 _pthread_start + 136
10 libsystem_pthread.dylib        0x1a10 thread_start + 8

JavaScriptCore libpas scavenger
0  libsystem_kernel.dylib         0x1b1c __psynch_cvwait + 8
1  libsystem_pthread.dylib        0xfd4 _pthread_cond_wait + 1228
2  JavaScriptCore                 0x15830f4 scavenger_thread_main + 1316
3  libsystem_pthread.dylib        0x24d4 _pthread_start + 136
4  libsystem_pthread.dylib        0x1a10 thread_start + 8

Thread
0  libsystem_kernel.dylib         0x96d0 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x19b0 _pthread_wqthread + 364
2  libsystem_pthread.dylib        0x1a04 start_wqthread + 8

Thread
0  libsystem_pthread.dylib        0x19fc start_wqthread + 438
code snippet of PhotoListViewController in MyApp
extension PhotoListViewController {

    func startDownloadImage(_ index: Int = 0) {
        guard let photoList,
              index < photoList.count else {
            return
        }

        let urlString = photoList[index]
        let indexPath = IndexPath(item: index, section: 1)
        if let url = URL(string: urlString) {
            if ImageCache.default.isCached(forKey: urlString) {
                ImageCache.default.retrieveImage(forKey: urlString, options: []) {[weak self] result in
                    switch result {
                    case .success(let imageResult):
                        self?.cacheCellSize(imageResult.image?.size, andReloadTableViewAt: indexPath)
                    case .failure(let error):
                        print("retrive image \(urlString) failed: \(error.localizedDescription)")
                    }
                } // line 30
                // 继续下载下一张 // line 31
                startDownloadImage(index + 1) // line 32
            } else { // line 33
                print("debug download start➡️:", urlString)
                ImageDownloader.default.downloadImage(with: url, options: .init()) { [weak self] result in
                    var success: Bool = false
                    switch result {
                    case .success(let value):
                        if let urlString = value.url?.absoluteString {
                            success = true
                            ImageCache.default.store(value.image, original: value.originalData, forKey: urlString, cacheSerializer: KingFisherHelper.getCacheSerializer())
                            self?.cacheCellSize(value.image.size, andReloadTableViewAt: indexPath)
                        }
                    case .failure(let error):
                        success = false
                        print(error)
                    }
                    print("debug download end✅ success: \(success),:", urlString)
                    // 继续下载下一张 // line 49
                    self?.startDownloadImage(index + 1) // line 50
                } // line 51
            }
        }
    }

    private func cacheCellSize(_ size: CGSize?, andReloadTableViewAt indexPath: IndexPath) {
        guard let size else {
            return
        }

        let height = tableView.frame.size.width / size.width * size.height
        cachedRowHeights[indexPath.row] = height
        execute {
            self.tableView.reloadData()
        }
    }
}
Data
Device
Model:iPhone 15 Pro Max
Orientation:Face Up
RAM free: 87.67 MB
Disk free: 69.77 GB
Operating System
Version:17.2.0
Orientation:Portrait
Jailbroken:No
Crash
Date:Dec 18, 2023, 9:31:34 AM
Kingfisher version: 7.6.2

Reproduce

It seems challenging to reproduce.In my App, users encountered this crash / all users = 0.006%.

onevcat commented 11 months ago

Thanks for reporting this!

From the stack it happens at closure #1 in PhotoListViewController.startDownloadImage(_:) + 30 (PhotoListViewController+ImageDownload.swift:30). Do you have any idea on which line in the code exactly this is at?

bugaco commented 11 months ago

Thanks for reporting this!

From the stack it happens at closure #1 in PhotoListViewController.startDownloadImage(_:) + 30 (PhotoListViewController+ImageDownload.swift:30). Do you have any idea on which line in the code exactly this is at?

Thanks for the reply! I have edited my first comment and added some line number:

image

I'm a bit confused about the trace, "line 30" is "}". Is it possible that it actually refers to line 32?🤔

onevcat commented 11 months ago

@bugaco

Not sure about what is going on with the current information.

Do you have the crash reason, say, something like SIGTRAP or EXC_BAD_ACCESS attached to the report?

bugaco commented 11 months ago

@bugaco

Not sure about what is going on with the current information.

Do you have the crash reason, say, something like SIGTRAP or EXC_BAD_ACCESS attached to the report?

@onevcat Yeah, the crash reason is :

Crashed: com.apple.main-thread
EXC_BREAKPOINT 0x0000000104959884
onevcat commented 11 months ago

Ummm...

So I guess this basically means the dispatch framework is not happy with something. Do you have any "diagnostic messages" in the received crash report? Maybe there is some useful reason.

bugaco commented 10 months ago

@onevcat I checked Google Crashlytics, but do not find the "diagnostic messages"🤔