justeat/JustLog

Fatal Exception: NSInvalidArgumentException -[__NSCFNumber count] Logger.log(_:_:error:userInfo:_:_:_:)

Closed this issue · 12 comments

Hi,

Please let me know how to fix the following issue in your lib.
Thanks

Fatal Exception: NSInvalidArgumentException
-[__NSCFNumber count]: unrecognized selector sent to instance 0x8000000000000000
Logger.log(::error:userInfo:::_:)
keyboard_arrow_down

Fatal Exception: NSInvalidArgumentException
0 CoreFoundation 0x1a4112754 __exceptionPreprocess
1 libobjc.A.dylib 0x1b8bd97a8 objc_exception_throw
2 CoreFoundation 0x1a4015c3c -[NSOrderedSet initWithSet:copyItems:]
3 CoreFoundation 0x1a41152ac forwarding
4 CoreFoundation 0x1a41175b0 CF_forwarding_prep_0
5 MyApp. 0x100b40efc Logger.log(
::error:userInfo::::) ()
6 MyApp. 0x100b412a0 Logger.verbose(:error:userInfo::::)
7 MyApp. 0x100b40484 Logger.verbose(:error:userInfo::::)

@gigisommo could you help me?

Hi @Ewg777,
do you have a snippet of code to reproduce the crash? Sadly the stack trace is not very helpful to understand this crash.

@gigisommo here it is


final class Foo {

    private let queue: OperationQueue = {
        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = 1
        return queue
    }()

    func sendAsync() {
        queue.addOperation {
            log.verbose("queue start"). <--- here is the crash
            send()
            log.verbose("queue end")
        }
    }

Thank you. I’m looking into it

I tried by adding the snippet to the example app, but it works for me. Please take a look at the attached screenshot. Any other advice on how to reproduce it? Should I use any specific version of iOS?
Screenshot 2021-07-28 at 13 02 56

You need to create as many threads as possible

final class Foo {

    private let queue: OperationQueue = {
        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = 100
        return queue
    }()

    func sendAsync() {
        queue.addOperation {
            log.verbose("queue start"). <--- here is the crash
            send()
            log.verbose("queue end")
        }
    }

    func send() {
           print(123)
     }
}


...
let a = Foo()
for _ in 1...1_000_000 {
  a.sendAsync()
}

Are you testing it on a real device or on the simulator?

Real customers' devices

My guess is that even if you remove the calls to JustLog inside the addOperation closure it will crash anyway. When you do the for _ in 1...1_000_000 your are creating 1 million objects into the heap and probably they fills the available memory. On top of that, the objects are created quickly from the main thread and the operation queue doesn't have the time to perform them since it runs with lower priority, so they all remain into the memory. You can see that the memory indicator in Xcode will show a high level of memory usage.

Based on my guess, that the crash:
-[__NSCFNumber count]: unrecognized selector sent to instance 0x8000000000000000
should always be similar in every crash report, but the class shouldn't always be the same. It happens because the app access memory on the stack and so it takes a random object.
If this is the case, JustLog isn't the root problem of the crash.

I run the code you provided in the simulator with a for loop with 10000 elements and it works without any issue.

1 million objects just an example to show the idea. The lib's code use the Set without synchronisation https://github.com/justeat/JustLog/blob/master/JustLog/Classes/Logger.swift#L213
In this case destinations 0x1a4015c3c -[NSOrderedSet initWithSet:copyItems:]

We are aware of some minor concurrency issues in the library. We plan to work on those in this quarter. I created another ticket with the details you gave here. @albertodebortoli FYI

I'm gonna go ahead and close this as we are deprecating the component and archiving the repo.