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

Crash in 1.8.2 #219

Closed
kcharwood opened this issue May 15, 2014 · 17 comments
Closed

Crash in 1.8.2 #219

kcharwood opened this issue May 15, 2014 · 17 comments

Comments

@kcharwood
Copy link

We're close to shipping a new product, so we haven't made the jump to 2.0 yet.

We did see a strange crash come in overnight last night, and wanted to see if anyone here had any insight...

0   CoreFoundation 0x2f287e83 __exceptionPreprocess + 131
1   libobjc.A.dylib 0x395e46c7 objc_exception_throw + 39
2   CoreFoundation 0x2f1bdff9 -[__NSArrayI objectAtIndex:] + 177
3   AppName 0x00358ab5 -[TyphoonTypeDescriptor initWithTypeCode:] (TyphoonTypeDescriptor.m:92)
4   AppName 0x003587d9 +[TyphoonTypeDescriptor descriptorWithTypeCode:] (TyphoonTypeDescriptor.m:63)
5   AppName 0x0034f895 +[TyphoonIntrospectionUtils typeForPropertyWithName:inClass:] (TyphoonIntrospectionUtils.m:43)
6   AppName 0x0033fbeb -[NSObject(TyphoonIntrospectionUtils) typeForPropertyWithName:] (NSObject+TyphoonIntrospectionUtils.m:31)
7   AppName 0x003492ef -[TyphoonComponentFactory(InstanceBuilder) doPropertyInjection:property:] (TyphoonComponentFactory+InstanceBuilder.m:150)
8   AppName 0x00349181 -[TyphoonComponentFactory(InstanceBuilder) doPropertyInjectionEventsOn:withDefinition:] (TyphoonComponentFactory+InstanceBuilder.m:129)
9   AppName 0x00348c49 -[TyphoonComponentFactory(InstanceBuilder) buildInstanceWithDefinition:] (TyphoonComponentFactory+InstanceBuilder.m:55)
10  AppName 0x0034b09f -[TyphoonComponentFactory(TyphoonDefinitionRegisterer) objectForDefinition:] (TyphoonComponentFactory.m:319)
11  AppName 0x00338a35 -[TyphoonComponentFactory(SwizzledObjectForDefinition) nkp_objectForDefinition:] (TyphoonComponentFactory+SwizzledObjectForDefinition.m:26)
12  AppName 0x0034a405 -[TyphoonComponentFactory componentForKey:] (TyphoonComponentFactory.m:151)
13  AppName 0x00352af9 -[TyphoonPropertyInjectedByReference withFactory:computeValueToInjectOnInstance:] (TyphoonPropertyInjectedByReference.m:41)
14  AppName 0x003493ff -[TyphoonComponentFactory(InstanceBuilder) doPropertyInjection:property:] (TyphoonComponentFactory+InstanceBuilder.m:160)
15  AppName 0x00349181 -[TyphoonComponentFactory(InstanceBuilder) doPropertyInjectionEventsOn:withDefinition:] (TyphoonComponentFactory+InstanceBuilder.m:129)
16  AppName 0x00348c49 -[TyphoonComponentFactory(InstanceBuilder) buildInstanceWithDefinition:] (TyphoonComponentFactory+InstanceBuilder.m:55)
17  AppName 0x0034b09f -[TyphoonComponentFactory(TyphoonDefinitionRegisterer) objectForDefinition:] (TyphoonComponentFactory.m:319)
18  AppName 0x00338a35 -[TyphoonComponentFactory(SwizzledObjectForDefinition) nkp_objectForDefinition:] (TyphoonComponentFactory+SwizzledObjectForDefinition.m:26)
19  AppName 0x0034a405 -[TyphoonComponentFactory componentForKey:] (TyphoonComponentFactory.m:151)
20  AppName 0x003507db -[TyphoonParameterInjectedByReference withFactory:setArgumentOnInvocation:] (TyphoonParameterInjectedByReference.m:42)
21  AppName 0x0034d8a1 -[TyphoonInitializer(InstanceBuilder) newInvocationInFactory:] (TyphoonInitializer+InstanceBuilder.m:47)
22  AppName 0x00348db5 -[TyphoonComponentFactory(InstanceBuilder) initializeInstanceWithDefinition:] (TyphoonComponentFactory+InstanceBuilder.m:76)
23  AppName 0x00348c17 -[TyphoonComponentFactory(InstanceBuilder) buildInstanceWithDefinition:] (TyphoonComponentFactory+InstanceBuilder.m:51)
24  AppName 0x0034b09f -[TyphoonComponentFactory(TyphoonDefinitionRegisterer) objectForDefinition:] (TyphoonComponentFactory.m:319)
25  AppName 0x00338a35 -[TyphoonComponentFactory(SwizzledObjectForDefinition) nkp_objectForDefinition:] (TyphoonComponentFactory+SwizzledObjectForDefinition.m:26)
26  AppName 0x0034a405 -[TyphoonComponentFactory componentForKey:] (TyphoonComponentFactory.m:151)
27  AppName 0x003507db -[TyphoonParameterInjectedByReference withFactory:setArgumentOnInvocation:] (TyphoonParameterInjectedByReference.m:42)
28  AppName 0x0034d8a1 -[TyphoonInitializer(InstanceBuilder) newInvocationInFactory:] (TyphoonInitializer+InstanceBuilder.m:47)
29  AppName 0x00348db5 -[TyphoonComponentFactory(InstanceBuilder) initializeInstanceWithDefinition:] (TyphoonComponentFactory+InstanceBuilder.m:76)
30  AppName 0x00348c17 -[TyphoonComponentFactory(InstanceBuilder) buildInstanceWithDefinition:] (TyphoonComponentFactory+InstanceBuilder.m:51)
31  AppName 0x0034b09f -[TyphoonComponentFactory(TyphoonDefinitionRegisterer) objectForDefinition:] (TyphoonComponentFactory.m:319)
32  AppName 0x00338a35 -[TyphoonComponentFactory(SwizzledObjectForDefinition) nkp_objectForDefinition:] (TyphoonComponentFactory+SwizzledObjectForDefinition.m:26)
33  AppName 0x0034a405 -[TyphoonComponentFactory componentForKey:] (TyphoonComponentFactory.m:151)
... More stuff non typhoon related

Looking at the line that crashed, it looks like there is an assumption made that the resulting components array will always contain two items. Can anyone think of any reason why that would happen given naming convention of a typeCode in Typhoon?

Should there be a check there to confirm there are two items before proceeded with calling the array? Would it be possible to issue a 1.8.3 hotfix if that is the case (I know 2.0 is the version you are looking to support, but its too late in the game to bring in a new version for us right now).

Let me know your thoughts.

🍻

@jasperblues
Copy link
Member

That does indeed look like a bug that was fixed in 2.0.

Its actually really easy to upgrade - we strongly recommend this.

@jasperblues
Copy link
Member

Actually on 2nd look at that trace, I'm not sure that that is the bug that I had in mind.

Unfortunately, as we're a free and volunteer-based project it becomes a personal out-of-pocket expense for us to support older versions. Our limited resources means we can't always do this.

However, you're welcome to engage in some professional consulting / support with Al Digit or myself.

Otherwise, let's get you onto version 2 and we'll continue.

@kcharwood
Copy link
Author

Thanks @jasperblues. To clarify, are you now saying this is fixed in 2.0, or potentially not?

Obviously at this point in our testing cycle, we're looking for small, targeted fixes, not wholesale upgrades to a library.

If this is fixed in 2.0, could you point me to the potential fix and let me see if I can cherry-pick it over into 1.8.x fork?

@jasperblues
Copy link
Member

Sorry. I'm saying I'm not sure. At first the description reminded me of an issue with early versions of runtime args.

Please put a breakpoint before that crashing line and tell me value of the 'typeCode' string that has suffix '>'. That assumption about array components has always been correct until now - a protocol name in angle brackets.

@jasperblues
Copy link
Member

I'm available on Skype - 'jasperblues'

@alexgarbarev
Copy link
Contributor

@kcharwood can you share your property declaration which cause this crash? You can see property name in debugger in [TyphoonIntrospectionUtils typeForPropertyWithName:inClass:] call

@jasperblues
Copy link
Member

@alexgarbarev 👍 and @kcharwood also the TyphoonDefinition from the assembly?

@kcharwood
Copy link
Author

I've got a couple of meeting stacked up this morning. After that, I'll grab that info and attach it here.

@kcharwood
Copy link
Author

We've only seen this once, so we can't actually reproduce this. I'm not exactly sure which property caused the crash, or how to grab that information...

Here is our (obscured) definition.

  return [TyphoonDefinition
          withClass:[Obscured class]
          initialization:^(TyphoonInitializer *initializer) {
            initializer.selector = @selector(initWithObscuredArgument1:ObscuredArgument2:ObscuredArgument3:ObscuredArgument4:);
            [initializer injectWithDefinition:[self ObscuredMethod1]];
            [initializer injectWithDefinition:[self ObscuredMethod2]];
            [initializer injectWithDefinition:[self ObscuredMethod3]];
            [initializer injectWithDefinition:[self ObscuredMethod4]];
          } properties:^(TyphoonDefinition *definition) {
            definition.scope = TyphoonScopePrototype;
          }];

@alexgarbarev
Copy link
Contributor

Crash call stack says that something going wrong during property injection. Check properties of objects, received by ObscuredMethod1, ObscuredMethod2, ObscuredMethod3, ObscuredMethod4.

Also make sure that all typhoon calls was on same thread, since typhoon 1.8.2 is not threaded-safe

@larsacus
Copy link

I finally caught this in the debugger today. I tried capturing all of the information that was requested above. A couple of strange things that I noticed while poking around the stack trace:

  1. hasSuffix: in TyphoonTypeDescriptor.m:90 was returning YES for a string that should not have been returning true
  2. The buffer that was used to populate typeDescriptor looks to be incorrect based on the contents of the const char *attrs = property_getAttributes() in the lines before that is populating buffer
(lldb) frame select 2
frame #2: 0x004cc5d0 SuperSuccessfulApp`-[TyphoonTypeDescriptor initWithTypeCode:](self=0x16d34650, _cmd=0x005ee85e, typeCode=0x16d33c20) + 880 at TyphoonTypeDescriptor.m:92
   89               }
   90               else if ([typeCode hasSuffix:@">"]) {
   91                   NSArray *components = [typeCode componentsSeparatedByString:@"<"];
-> 92                   NSString *protocol = [components[1] stringByReplacingOccurrencesOfString:@">" withString:@""];
   93                   NSString *class = components[0];
   94   
   95                   _protocol = NSProtocolFromString(protocol);

(lldb) bt 5
* thread #5: tid = 0x282c1f, 0x3a1a3cc0 libobjc.A.dylib`objc_exception_throw, queue = 'NSOperationQueue 0x16d3c900', stop reason = breakpoint 1.1
    frame #0: 0x3a1a3cc0 libobjc.A.dylib`objc_exception_throw
    frame #1: 0x2f9432f0 CoreFoundation`-[__NSArrayI objectAtIndex:] + 176
  * frame #2: 0x004cc5d0 SuperSuccessfulApp`-[TyphoonTypeDescriptor initWithTypeCode:](self=0x16d34650, _cmd=0x005ee85e, typeCode=0x16d33c20) + 880 at TyphoonTypeDescriptor.m:92
    frame #3: 0x004cc0ac SuperSuccessfulApp`+[TyphoonTypeDescriptor descriptorWithTypeCode:](self=0x006e3290, _cmd=0x005edac6, typeCode=0x16d344c0) + 80 at TyphoonTypeDescriptor.m:63
    frame #4: 0x004bb272 SuperSuccessfulApp`+[TyphoonIntrospectionUtils typeForPropertyWithName:inClass:](self=0x006e2d7c, _cmd=0x005ebc36, propertyName=0x16ecc7a0, clazz=0x006e16c0) + 386 at TyphoonIntrospectionUtils.m:43

(lldb) po typeCode
MMRedactedHandler

(lldb) p (BOOL)[typeCode hasSuffix:@">"]
(BOOL) $28 = YES

(lldb) frame select 3
frame #3: 0x004cc0ac SuperSuccessfulApp`+[TyphoonTypeDescriptor descriptorWithTypeCode:](self=0x006e3290, _cmd=0x005edac6, typeCode=0x16d344c0) + 80 at TyphoonTypeDescriptor.m:63
   60   
   61   + (TyphoonTypeDescriptor *)descriptorWithTypeCode:(NSString *)typeCode
   62   {
-> 63       return [[[self class] alloc] initWithTypeCode:typeCode];
   64   }
   65   
   66   + (TyphoonTypeDescriptor *)descriptorWithClassOrProtocol:(id)classOrProtocol;

(lldb) bt 5
* thread #5: tid = 0x282c1f, 0x3a1a3cc0 libobjc.A.dylib`objc_exception_throw, queue = 'NSOperationQueue 0x16d3c900', stop reason = breakpoint 1.1
    frame #0: 0x3a1a3cc0 libobjc.A.dylib`objc_exception_throw
    frame #1: 0x2f9432f0 CoreFoundation`-[__NSArrayI objectAtIndex:] + 176
    frame #2: 0x004cc5d0 SuperSuccessfulApp`-[TyphoonTypeDescriptor initWithTypeCode:](self=0x16d34650, _cmd=0x005ee85e, typeCode=0x16d33c20) + 880 at TyphoonTypeDescriptor.m:92
  * frame #3: 0x004cc0ac SuperSuccessfulApp`+[TyphoonTypeDescriptor descriptorWithTypeCode:](self=0x006e3290, _cmd=0x005edac6, typeCode=0x16d344c0) + 80 at TyphoonTypeDescriptor.m:63
    frame #4: 0x004bb272 SuperSuccessfulApp`+[TyphoonIntrospectionUtils typeForPropertyWithName:inClass:](self=0x006e2d7c, _cmd=0x005ebc36, propertyName=0x16ecc7a0, clazz=0x006e16c0) + 386 at TyphoonIntrospectionUtils.m:43

(lldb) po typeCode
T@"MMRedactedHandler"

(lldb) frame select 4
frame #4: 0x004bb272 SuperSuccessfulApp`+[TyphoonIntrospectionUtils typeForPropertyWithName:inClass:](self=0x006e2d7c, _cmd=0x005ebc36, propertyName=0x16ecc7a0, clazz=0x006e16c0) + 386 at TyphoonIntrospectionUtils.m:43
   40           buffer[len] = '\0';
   41   
   42           NSString *typeCode = [NSString stringWithCString:buffer encoding:NSUTF8StringEncoding];
-> 43           typeDescriptor = [TyphoonTypeDescriptor descriptorWithTypeCode:typeCode];
   44       }
   45       return typeDescriptor;
   46   }

(lldb) bt 5
* thread #5: tid = 0x282c1f, 0x3a1a3cc0 libobjc.A.dylib`objc_exception_throw, queue = 'NSOperationQueue 0x16d3c900', stop reason = breakpoint 1.1
    frame #0: 0x3a1a3cc0 libobjc.A.dylib`objc_exception_throw
    frame #1: 0x2f9432f0 CoreFoundation`-[__NSArrayI objectAtIndex:] + 176
    frame #2: 0x004cc5d0 SuperSuccessfulApp`-[TyphoonTypeDescriptor initWithTypeCode:](self=0x16d34650, _cmd=0x005ee85e, typeCode=0x16d33c20) + 880 at TyphoonTypeDescriptor.m:92
    frame #3: 0x004cc0ac SuperSuccessfulApp`+[TyphoonTypeDescriptor descriptorWithTypeCode:](self=0x006e3290, _cmd=0x005edac6, typeCode=0x16d344c0) + 80 at TyphoonTypeDescriptor.m:63
  * frame #4: 0x004bb272 SuperSuccessfulApp`+[TyphoonIntrospectionUtils typeForPropertyWithName:inClass:](self=0x006e2d7c, _cmd=0x005ebc36, propertyName=0x16ecc7a0, clazz=0x006e16c0) + 386 at TyphoonIntrospectionUtils.m:43

(lldb) po propertyName
authenticationState

(lldb) po clazz
MMRESTAPIRequestSerializer

(lldb) p attrs
(const char *) $34 = 0x0058a0c2 "T@"<MMAuthenticationState>",&,N,V_authenticationState"
(lldb) p buffer
(char [256]) $35 = "T@"MMRedactedHandler""
(lldb) p e
(const char *) $36 = 0x0058a0de ",&,N,V_authenticationState"
(lldb) p len
(int) $37 = 28
(lldb) po typeCode
T@"MMRedactedHandler"

@alexgarbarev
Copy link
Contributor

Thanks for info @larsacus.
Checked your debug info. Yes, code you pointed looks strange for me too, but I think it should work correct.
I think crash have another reason.
In your log I see

* thread #5: tid = 0x282c1f, 0x3a1a3cc0 libobjc.A.dylib`objc_exception_throw, queue = 'NSOperationQueue 0x16d3c900'

Looks like you calling Typhoon from NSOperationQueue, but as I said before, Typhoon 1.8.2 is not threaded safe (it become threaded safe since 564fe91). In code you pointed, 'buffer' is static, so shared between threads, I think its a problem.
Is your NSOperation serial? Does typhoon called from another thread (main for example)?

@larsacus
Copy link

That particular NSOperaionQueue that this was run on is not serial. Before I posted the trace above, we came to the same conclusion that it was likely a threading issue that caused buffer to contain the contents of another thread's initialization.

@jasperblues
Copy link
Member

@larsacus We may be able to back-port the tread-safety for you. But again we recommend upgrading to Typhoon 2.0.

  • There are loads of other new features
  • Lots of bug-fixes and active support
  • Its really simple to upgrade, I can help you do this over a Skype call if you like. (I estimate less effort here than backporting).

@jasperblues
Copy link
Member

@alexgarbarev Good analysis and well spotted!

@jasperblues
Copy link
Member

@larsacus It appears you have a work-around, meanwhile this issue is addressed in Typhoon 2.x

Therefore we'll close this issue for now. Please reopen or raise a new one if you still have some concerns.

@larsacus
Copy link

larsacus commented Jun 9, 2014

We've "upgraded" to 2.0 as a workaround

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

4 participants