I've got a repeating NSTimer that I invalidate manually some time before I dealloc the object that owns the callback that is invoked by the timer. I verify that when I invalidate the timer, the callback is not being called anymore. When the object deallocs, an instant later I get an EXC_BAD_ACCESS. The crash is correlated with whether I invalidate the timer or not, i.e. if I don't invalidate it, there is no crash.
Does anyone know why this might be happening? I don't see why the timer would try to access the callback for the dealloc'ed object, which is what seems to be happening. I'm at a loss how to debug this further. The callstack just says:
#0 0x02f05c93 in objc_msgSend
#1 0x00000001 in ??
#2 0x02d255fa in CFRunLoopRunSpecific
#3 0x02d248a8 in CFRunLoopRunInMode
#4 0x037de89d in GSEventRunModal
#5 0x037de962 in GSEventRun
#6 0x00863372 in UIApplicationMain
#7 0x00002e40 in main at main.m:13
UPDATE: I have determined it is not the timer but a leak resulting from my parent object calling dealloc (the non-invalidating timer was preventing dealloc from calling). It would still be useful to hear advice on how to debug things when I hit a wall with the callstack, if it is even possible, so I'll leave this question up.
When you invalidate an NSTimer, the receiver sends a release to the target and userInfo parameters of timerWithTimeInterval:target:selector:userInfo:repeats:. Is it possible you are referring to these objects or have some incorrect memory-management with one of these objects?
One way to debug this is to make use of NSZombie.
Related
I'm trying to analyze the core dump of one of my applications, but I'm not able to find the reason for the crash.
When I run gdb binary file corefile I see the following output:
Program terminated with signal SIGKILL, Killed.
#0 0xfedcdf74 in _so_accept () from /usr/lib/libc.so.1
(gdb)
But I am pretty sure that no one has executed kill -9 <pid>. With info thread, I can see all the threads launched by the application, but I can see nothing special about any thread.
By running bt full or maint info sol-threads I don't find anything that leads to the bug. I just see the stack trace for each thread without any information about the bug.
Finally I've found a thread which causes the kill signal.
#0 0xfedcebd4 in _lwp_kill () from /usr/lib/libc.so.1
#1 0xfed67bb8 in raise () from /usr/lib/libc.so.1
#2 0xfed429f8 in abort () from /usr/lib/libc.so.1
#3 0xff0684a8 in __cxxabiv1::__terminate(void (*)()) () from /usr/local/lib/libstdc++.so.5
#4 0xff0684f4 in std::terminate() () from /usr/local/lib/libstdc++.so.5
#5 0xff068dd8 in __cxa_pure_virtual () from /usr/local/lib/libstdc++.so.5
#6 0x00017f40 in A::method (this=0x2538d8) at A.cc:351
Class A inherits of an abstact class and in the line 351 a virtual function declared in the abstract class and defined in A is called. I donĀ“t understand why if object A exists the call to the virtual base function crashes.
That SIGKILL could be caused by your app exceeding some resource limit. Try to get the system log and see if there are any resource limit exceeded messages.
References
Solaris Administration Guide: Resource Controls
I am trying to debug a crash in gdb where is core dumped on this thread. There is other 40+ threads going on at the same time. How do I figure out where this thread 42 is started from?
Also, why the last line (frame #0) is not showing up?
Thread 42 (Thread 0x2aaba65ce940 (LWP 15854)):
#0 0x0000003a95605b03 in __nptl_deallocate_tsd () from /lib64/libpthread.so.0
#1 0x0000003a9560684b in start_thread () from /lib64/libpthread.so.0
#2 0x0000003a946d526d in clone () from /lib64/libc.so.6
#3 0x0000000000000000 in ?? ()
I am using gdb version 7.7
How do I figure out where this thread 42 is started from?
You can't: neither GDB, nor the OS keeps track of "who started this thread". (It is also often quite useless to know where a particular thread was created).
What you could do is either put instrumentation into your own calls to pthread_create and log "thread X created thread Y", or use catch syscall clone, and print creation stack traces in GDB, then match them later to the crashed thread (match its LWP to the return value of clone earler).
Also, why the last line (frame #0) is not showing up?
You mean frame #3. It doesn't exist -- clone is where the thread is borne (comes to existence).
P.S. Installing libc debug symbols so you can see where inside __nptl_deallocate_tsd the thread crashed is more likely to provide clues than knowing thread creation details.
Hi i using winapi's QueueUserAPC to invoke an apc function call in another thread.
my question is, what is the best practice for passing a parameter to it.
i refer to the object lifetime and allocation/deallocation responsibility.
DWORD WINAPI QueueUserAPC(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
i am using the dwData to pass the parameter to pass a pointer to some data and i was wondering how i should handle it.
i need to make sure that it lives until the receiving thread finished using it.
should i use a smart pointer to make sure that data is deallocated when no longer used?
i guess that allocation in the calling thread and dealloc. in the receiving is possible but probably not such a good thing.
anything else that can be done?
i think i would like to avoid synchronization between the two only to notify that the receiving thread is done with the data...
thanks!
Alloc'ing in the sending thread and dealloc'ing in the receiving one is easy, but it has the main drawback that it may leak, even if you handle the sending failure, the receiving thread may finish before having a chance to execute the APC.
Probably your easiest way to avoid the leak is to create a queue for sent data -maybe a queue per thread- and when thread finishes, you traverse the thread queue and free all the pending data.
But as usual, the devil is in the details...
i have a subclass of NSOperation which have managedObject as one of its property.
I need to add multiple operation to nsoperationqueue & observe their finish.
For each NSOperation instance i created a new managed object as Apple documentation state "Create a separate managed object context for each thread and share a single persistent store coordinator.".
Once the first operation is finished i get following crash log
#0 0x34970c98 in objc_msgSend ()
#1 0x3608704e in -[_PFArray dealloc] ()
#2 0x36084b80 in -[_PFArray release] ()
#3 0x3179b1a0 in CFRelease ()
#4 0x3179deba in _CFAutoreleasePoolPop ()
#5 0x30d7bbb4 in NSPopAutoreleasePool ()
#6 0x30d91e1c in -[__NSOperationInternal start] ()
#7 0x30d91a7e in -[NSOperation start] ()
#8 0x30df7eca in ____startOperations_block_invoke_2 ()
#9 0x33a248e6 in _dispatch_call_block_and_release ()
#10 0x33a1a532 in _dispatch_worker_thread2 ()
#11 0x368bf590 in _pthread_wqthread ()
#12 0x368bfbc4 in start_wqthread ()
From logs it seems some object is getting over-release.How i can get which object is over-release?
App is run with NSZombieEnabled but only above info is received.
do the NsOperation maintain its own autorelease pool?
Here are your clues:
#7 0x30d91a7e in -[NSOperation start] ()
It is something you are releasing in your operation.
#5 0x30d7bbb4 in NSPopAutoreleasePool ()
It is an object that is autoreleased. That does not necessarily mean you have written the autorelease method call. Objects that are created by convenience methods like [NSString stringWithFormat:...] are autoreleased before they are returned. So look for either a place in your operation code where you are calling autorelease or a place where you are creating an object without the alloc-init pattern.
Yes, an NSOperation maintains its own autorelease pool. You shouldn't have to worry about that. If you only release objects when you are done with them, and only autorelease objects when you will be done with them by the end of the method scope (or calling method scope if returning them) you should be fine.
#2 0x36084b80 in -[_PFArray release] ()
It is an object stored in an array (not the array itself) that is being overreleased.
An error of that kind means you are either releasing or autoreleasing an object when you shouldn't, or you are not retaining an object when you should. It could be either an incorrect release or an incorrect autorelease, even though the error occurs with the autorelease pool. The autorelease could be correct and the release could be incorrect. Either way the error will happen when the autorelease pool is drained because that happens later.
Error Log says:
bool _WebTryThreadLock(bool), 0x3c689f0: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
App structure:
worker threads are detached from the MainThread as new data is needed via user interaction, each worker thread feeds data into its own slot in an array. The problem arises only when I use the NavigationController to go "back" to the previous view WHILE a thread is still gathering data. I've tried to send a [NSThread exit] to each thread upon viewWillDisappear thats not going to work...
Any suggestions on thread clean-up upon poppin' the view controller?
So apparently i needed to build in checks to the runloop as well as the didRecieveData loop to watch for a global variable to indicate if the view has disappeared. This in turn needs to toggle the global var, causing all open threads to cancel the connection as well as exit the thread.