• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: CFFileDescriptor fd leak?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: CFFileDescriptor fd leak?


  • Subject: Re: CFFileDescriptor fd leak?
  • From: "A.M." <email@hidden>
  • Date: Thu, 20 Aug 2009 19:42:36 -0400

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


On Aug 20, 2009, at 6:47 PM, Dave Keck wrote:

Hey,

I ran your test code and saw the same results. After tweaking the code a
bit, I found that to have the kqueues cleaned up, you have to create a run
loop source for the CFFD, add it to the run loop, and then remove it from
the run loop. Here's the tweaked code:
==============================


#include <CoreFoundation/CoreFoundation.h>
#include <unistd.h>
#include <sys/event.h>

static void junkCallback(CFFileDescriptorRef fdref, CFOptionFlags
callBackTypes, void *info) {}

int main(int argc, char *argv[])
{

   int i = 0;

   for (i = 0; i < 3; i++)
   {

       CFFileDescriptorRef fileDescriptor = nil;
       CFRunLoopSourceRef runLoopSource = nil;

       NSLog(@"CREATE %d", i);
       fileDescriptor = CFFileDescriptorCreate(NULL, 0, false,
junkCallback, NULL);
       runLoopSource = CFFileDescriptorCreateRunLoopSource(NULL,
fileDescriptor, 0);
       CFRunLoopAddSource([[NSRunLoop currentRunLoop] getCFRunLoop],
runLoopSource, kCFRunLoopDefaultMode);

NSLog(@"DESTROY %d", i);
CFRunLoopRemoveSource([[NSRunLoop currentRunLoop] getCFRunLoop],
runLoopSource, kCFRunLoopDefaultMode);
CFRelease(runLoopSource);
CFFileDescriptorInvalidate(fileDescriptor);
CFRelease(fileDescriptor);


   }

   sleep(-1);

   return 0;

}

==============================

I'd definitely consider your findings a bug. But I don't think it poses any
real issue, since CFFileDescriptor is useless unless it's used with a run
loop.


I'd say a radar is in order...


Hi Dave,

I shaved down the code from the previous email from code which did indeed add the CFFileDescriptor to the runloop and leaked. However, I did not remove the source from the runloop manually like you do above and the Apple example code (http://developer.apple.com/documentation/CoreFoundation/Reference/CFFileDescriptorRef/Reference/reference.html ) doesn't remove the runloop source either. Unfortunately, the code you laid out above does indeed sometimes leak a single kqueue fd (OS 10.5.8):

rd07:~ alex$ ./davekeck &
[1] 4880
rd07:~ alex$ lsof -p $! | grep KQUEUE
davekeck 4880 alex 4u KQUEUE count=0, state=0


If I run it with breakpoints on kqueue, close, and kevent in gdb, then the leak disappears, which indicates that the Apple code has a race condition. I noticed that close() is called in the __monitor_file_descriptor__ thread, so I suspect that without the thread created from the addition of a source, that close on the kqueue will never be called. The above code leaks sometimes due to a race condition in inter-thread communications- bizarrely, it leaks descriptor 4 which is the first that was allocated- I would have thought that the last one would leak...

With the following hack-around code (based on yours), the fd leak is permanently squelched:

#include <CoreFoundation/CoreFoundation.h>
#include <unistd.h>
#include <sys/event.h>

static void junkCallback(CFFileDescriptorRef fdref, CFOptionFlags
                         callBackTypes, void *info) {}

struct __FileDescriptorHackStruct
{
	int junkA;
	int junkB;
	int junkC;
	int internalKqueueDescriptor;
};

int main(int argc, char *argv[])
{

	int i = 0;

	for (i = 0; i < 3; i++)
    {

		CFFileDescriptorRef fileDescriptor = nil;
		CFRunLoopSourceRef runLoopSource = nil;

		fileDescriptor = CFFileDescriptorCreate(NULL, 0, false,
												junkCallback, NULL);
		runLoopSource = CFFileDescriptorCreateRunLoopSource(NULL,
															fileDescriptor, 0);
		CFRunLoopAddSource(CFRunLoopGetCurrent(),
						   runLoopSource, kCFRunLoopDefaultMode);

		CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
							  runLoopSource, kCFRunLoopDefaultMode);
		CFRelease(runLoopSource);

close(((struct __FileDescriptorHackStruct*)fileDescriptor)- >internalKqueueDescriptor);

		CFFileDescriptorInvalidate(fileDescriptor);
		CFRelease(fileDescriptor);

    }

	sleep(-1);

	return 0;

}

At least it is not leaking threads. Speaking of which, why does each file descriptor need to be watched by a new thread? Not even CFSocketManager is that dumb. In any case, this is looking so bad that I will likely need to implement my own CFFileDescriptor replacement.

Cheers,
M
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (Darwin)

iEYEARECAAYFAkqN328ACgkQqVAj6JpR7t4LUQCfamtzP0xV6GWEBNxpQRw6ZK+I
SuAAn3wouHd+LXixOKheQFJL3ccy2IuI
=iogu
-----END PGP SIGNATURE-----
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: CFFileDescriptor fd leak?
      • From: Dave Keck <email@hidden>
References: 
 >CFFileDescriptor fd leak? (From: "A.M." <email@hidden>)
 >Re: CFFileDescriptor fd leak? (From: Dave Keck <email@hidden>)

  • Prev by Date: Re: which pages of the file are in the cache
  • Next by Date: Re: CFFileDescriptor fd leak?
  • Previous by thread: Re: CFFileDescriptor fd leak?
  • Next by thread: Re: CFFileDescriptor fd leak?
  • Index(es):
    • Date
    • Thread