Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EASession Leaks

I have an app that connects to an accessory, and the EASession that I create in order to communicate with the accessory leaks when you disconnect the accessory.

When the accessory connects, I get a notification of this and check EAAccessoryManager's accessories collection for an accessory with a certain name that uses a certain protocol. When I find this I create an EASession object for that accessory with code:

-(void) openSession
{
   ...  // finds accessory object

   if (accessory)
   {
      [self closeSession];
      session = [EASession alloc];
      NSLog(@"alloc :: session retainCount: %i", session.retainCount);
      [session initWithAccessory:accessory forProtocol:SmokeSignalsProtocolName]; 
      NSLog(@"init  :: session retainCount: %i", session.retainCount);

      [[session inputStream] open]; 
      [[session outputStream] open]; 

      ... // other logic (pump run loop, etc..)
   }
}

-(void) closeSession
{
    if (session)
    {
       [[session inputStream] close]; 
       [[session outputStream] close]; 
       [session release], session = nil;
    }
}

Normally I have the alloc and init on one line, but what I've found (separating it out like this) is that the alloc gives +1 retain count (as you'd expect) BUT the iniWithAccessory:forProtocol: gives it +3 retain count when I would only expect +2 retainCount from the init method.

The leaks instrument also appears to support this:

enter image description here

Step by Step look at the leaks instrument:

  1. +1 retain count :: [???Accessory openSession] - this is where I alloc a new EASession.
  2. +1 retain count :: [EAInputStream iniWithAccessory:forSession:] The input stream holds a reference back to the owning session.
  3. +1 retain count :: [EAOutputStream initWithAccessory:forSession:] The output stream holds a reference back to the owning session.
  4. +1 retain count :: [EASession iniWithAccessory:forProtocol:] I have no idea why this is increasing the retain count of EASession. I believe this is responsible for the additional retain count that I can't account for... Not sure how this is supposed to be balanced. Is this Apple's bug and I need to call release an extra time to balance things.... Very VERY weird.
  5. -1 retain count :: [EAInputStream close] Cleans up step #2 above
  6. -1 retain count :: [EAOutputStream close] Cleans up step #3 above
  7. -1 retain count :: ???Accessory closeSession] Cleans up step #1 above1

So... Why am I leaking the EASession object? What's the proper way to use a EASession object to not leak?


Edit - EADemo Does Not Leak, but ...

EADemo connects to accessories, but it does not leak. Out of curiosity, I added an extra [_session retain] to make it leak so I could follow the malloc history of it in instruments. It was interesting to see some internal things called that were not called in the malloc history of my app.

enter image description here

You can see this has [EAAccessoryInternal removeSession:] called 3 times. This was never called in the malloc history of my app. I think this is key to why my EASession is not being released...

like image 650
Sam Avatar asked Apr 23 '12 21:04

Sam


1 Answers

I know this discussion is quite old now but I had exactly the same problem recently using ARC e.t.c. I've found that one way around it is by just not closing the input or output streams. Just have a class that deals with all input e.t.c and forward on the data on request to other parts of your application. You can re-alloc init the EASession object with no complaints from XCode so I'm assuming the old EASession is dealloc ed OK as it's no longer referenced by my APP. I haven't checked the leaks yet however.

like image 94
RASS Avatar answered Nov 15 '22 07:11

RASS