I'm working on a hobby project which I'm slowly updating in my spare time to help learn some new things. One stumbling block I've come across is working with Core Data in a separate thread. I've read Apple's documentation about Core Data concurrency and everything I read seemed straight forward enough so I began to update my project to load data on a background thread as I don't want to lockout the UI whilst things are loading.
The project works fine if the Core Data object is loaded on the main thread. It crashes if I switch to background loading.
At this stage, I can verify that:
The NSManagedObject loads on the thread and I can access it's properties
Outputting the data to the stdout works fine and looks correct.
A binary comparson of the data object loaded on the main thread and the data loaded on the background thread proves they are identical.
The actual problem occurs when I call a category implementation on NSData. I can verify the NSData object is fine when it's loaded on the background thread, it's only when I call a function to do some work on the NSData object after it's loaded do I get a problem. The problem is a EXC_BAD_ACCESS, which usually means the address of an object is wrong but it doesn't quite make any sense.
I'm probably just getting something obvious or simple wrong - but I just can't see the forest for the trees.
If you think you can offer any advice on this as it's driving my crazy then you can find the code here:
Edit post answer: Removed URL as project no longer exists.
Ok I've finally found out what the problem is. The decompression method was exceeding the stack size of the thread and therefore causing a weird & random EXC_BAD_ACCESS to be fired.
I would have expected the debugger to produce a more direct clue in this case.
So a valid 'stack overflow' problem, solved.
Related
I have a web application, using Spring-Boot. There is now a need for this application to use a custom dll (in house build dll file). There is nothing wrong with this dll, as we use it on our other applications, and have no problems with it.
To load the library in this new web application I'm writing, I have added the dll file to the procrun directory. This directory is on the library path, so that makes sense.
During startup I put in code to immediately load the dll, and also test some of its functionality. This works fine.
However, I have a timer, that schedules the execution of some functions, which may or may not include function calls to the dll.
At some point, about 10 minutes or so into execution, the service unexpected and seemingly without any valid reason, stops.
Although I try/catch exceptions at the appropriate logical places in code, there are no relevant log entries printed.
The Event Log shows something that reminds me of a null pointer exception:
Another bread crumb is that the event log will print something about the dll_unload. (see picture)
I need some help figuring out why the service is failing/stopping.
Kind Regards.
EDIT: After about three days of debugging and scratching my head, I came upon a forum thread that explained that this problem has something to do with the manner in which the system releases the memory during garbage collection. It seems that the dll in question was being unloaded by the garbage collector, even though it could still be called at some time later - which of course was the cause of the service falling over.
To solve the problem, I put in a timer that would call a method in the dll at three minute intervals (on my system this would not impact performance). I know this solution is a hack, but it works for me.
I'm developing a DirectShow CSource capture filter. It works fine, but when I close the program that is using the filter (in this case I'm testing with VLC, but the same happens with other programs), the program crashes (if I'm debugging it in Visual Studio then a breakpoint is triggered).
I've been hunting down this problem for some time now and found that both, my source filter and my source stream are not being released; this is, their reference counter is 1 at the end of the program, DllCanUnloadNow() function reports that there are 2 objects still in use, and, when CoUninitialize() is invoked, the program crashes.
I'm pretty sure that the reference counters are being handled correctly since I'm using the base classes implementation. The only unusual thing in my software that I can think of is that I'm using my own version of DllGetClassObject(): I configured the .DEF file to have MyDllGetClassObject() exported instead of DllGetClassObject() so I could insert some code before invoking the default implementation. I don't think this is a problem since I've checked that the reference counter of all objects I return at the end of MyDllGetClassObject() is 1.
I guess I'm missing something about the lifecycle of the filter, but can't figure out what (this is the very first capture filter I'm developing). Any suggestion?
Thank you in advance,
Guillermo
I finally figured out what was going on. The static method InitializeInstance in my source filter is invoked with bLoading == false and rclsid == <the GUID of my filter> at process shutdown. That seems to be the appropriate place to release that remaining reference counter from the filter instance.
I got the key idea of how important is to release all COM objects before CoUninitialize some time ago from another post on StackOverflow entitled DirectShow code crashes after exit (PushSourceDesktop sample). All I needed was just a little bit more knowledge on DirectShow filters lifecycle.
Anyway, thank you for your efforts, Roman, I know how vague this thread sounded from the beginning :)
I use Core Data in my application, and discovered some odd behavior of the simulator: When I add some data to Core Data in my app and quits the simulator using the "stop" button in XCode (or just press Cmd-Q) immediately, the data is not stored in the database the next time I start the simulator. After some testing, I found out, that the data is stored to disk:
immediately if I press the home button. (Almost - it is possible to quit the application before data is stored if quitting very fast.)
If I let the application run for some time (at least about 20 seconds) after adding data.
It does not help to call [NSManagedObjectContext save:]. The behavior is the same.
So my question is: What is the reason for this kind of behavior? Are there any way to force flushing to disk before quitting? And are there any risk that I can loose data this way when running on a device (personally, I do not see any, except a force close, but the odd behavior bothers me a bit)
Stopping the simulator with the stop button in Xcode is probably the same as smashing your iPhone with a hammer (but preserving the SSD). Basically, your app and everything else just stops. There's no reasonable way to ensure that data is saved when that happens.
You're probably using nested context's. If your context has a parent context, calling -save: will just save to that context, not to the file system.
Nested context are (usually) used to safely use a context on a background queue, and allowing a foreground context to save without having to incur the overhead of saving to the file system. The save to the file system will happen on a background queue and not block the main thread.
I too have been wrestling with this for a very long time and Daniel Eggert's answer under (2) above is the first - and only - useful answer I have found on the internet. I presume JRV is using the NSManagedDocumentContext from a UIManagedDocument. If this is the case then Apple's 'default' saving method is incomplete! Having adopted Daniel Eggert's solution my data is now preserving perfectly and is also immune to a simulator 'STOP' gesture. I recommend Daniel Eggert's answer under (2) above to anyone else wishing to write resilient code in this case.
I wrote an entire app, and I was just about to submit it to the app store, and in my final testing, I went back and added a few releases to ensure proper memory management was observed. And since then, I keep getting these random crashes. I've tried removing some or all of the release calls, I've tried retaining objects. I cleaned the project. I used NSZombieEnabled and that also is not helping. All this to not avail.
Most of the time, the console says provides no help. Usually the app loads, I put NSLogs in viewDidLoad, viewDidAppear, and viewWillAppear, and they all show up in the console, then it crashes.
Sometimes I also get EXC_BAD_ACCESS (and I know what that means). But its occurring randomly. So this doesn't make sense to me. Thanks for any help possible. I've written this whole app, and spent months on it. So I'm really stuck. Thank you.
Have you tried Build --> Analyze? It will search your code for leaks and other useful things you might have missed. Try that and see if it finds anything for you.
I agree with Rudy. It sounds like you're releasing something that is still in use. I would go back to the version that was working and start adding the releases one at a time til it causes the crash. Slow but effective debugging.
When you say that you "sometimes" get EXC_BAD_ACCESS, what do you get the rest of the time? Where does the crash stack indicate you're crashing? What messages do you get?
Random crashes usually indicate a timing problem. A common cause is accessing things on multiple threads. Are you? It can also mean timing differences based on network traffic.
Make sure the console doesn't indicate an exception rather than a memory violation. Usually there's something in the console that will be useful.
I have an old VW3/ENVY image with a parcel loaded as unmanaged code (exactly the situation Mastering ENVY/DEVELOPER warns against). Unfortunately, this problem happened a long time ago and it's too late to just "go back" to an image without the parcel loaded.
Apparently, there is a way to solve this problem (we have one development image where this has been solved, and there are normal configuration maps that contain the exact same code as the unmanaged parcel but they can't be loaded), but the exact way has long since been forgotten (and there are some problems with taking that particular dev image as the base for a new runtime image, so I need to find out how how to do it again).
In theory, it should be possible to remove the parcel and reload the code from a configuration map. In practice, all normal ways (using the ParcelBrowser or directly calling UnmanagedCode>>remove) fail. I even tried manually removing the offending selectors from the method dictionary, but past a certain point (involving a call to #primBecome:) the whole image hangs completely (I can't even drop into the debugger). I started hacking the instances of the classes and methods, hoping I'd trick ENVY into thinking that these particular methods are normal versioned code, but without any success yet.
Are there any smalltalk/envy gurus around that still remember enough of VW 3 to provide me with any pointers?
Status update
After a week of trying to solve the problem I finally made it, at least partially, so in case anyone's interested...
First, I had to fix file pointers for the umnanaged code (otherwise, all everything that tried to touch the methods would throw an exception). It looks like ENVY extends Parcel so that, in theory, all integer file pointers are changed to ENVY's void filepointer when loaded, but in my case, I had to do it manually (a Parcel provides enumeration for all selectors it defines). Another way would be to tweak the filePointer code, but that can't easily be done automatically on every image where it's needed.
Then, the parcel can be discarded, which drops the parcel information, but keeps the code. The official "Discard" mechanism needs to have a valid changes file (which envy doesn't use so it has to be set manually, and reset afterwards) and the parcel source (which we fortunately had).
To be able to make any changes to the methods (either manually, or via loading an application or class from ENVY), they need to get rid of their unmanaged status. This can be done by manually tweaking TheClass>>applicationAssocs (I also got rid of all references to the classes in UnmanagedCode sich as timestamps, and removed the reference to the discarded parcel). I actually had some info on how to get to this point from my boss, but I haven't been able to understand the instructions until I almost figured it out by myself.
This finally allowed me to load and reload all the Applications that contained the classes. In theory. In practice, the image still hung completely whenever I tried to load a newer version of the Application (that contained the code formerly in the parcel).
It turned out that the crashes had absolutely nothing to do with the code being unmanaged, but with the fact that the parcel in question modified InputState>>process:, where it caused an exception due to a missing and/or uninitialized class variable (the InputState>>initialize method wasn't called until after the new process: method was in place). I had to modify the Notifier class to dump all exceptions to a file to find out what was going on. Adding the class variable to the source of the class (instead of adding it via reflection), suspending the input processing thread via toBeLoadedCode and starting it again in the loaded method and creating a new version of the application solved even this problem.
Now everything works, in theory. In practice it's still unusable, because reloading the WindowSystem or VisualworksBase applications causes their initialization blocks to run, and a whole lot of settings are reset to their defaults - fonts and font sizes, window colors, UI settings... And there doesn't seem to be any way to just save the settings to a file and load them later on, or just to see what all the settings are (either the official Settings menu doesn't show everything, or we have a heavily tweaked image... so much for reconstructing it from scratch). But that's a completely different question.
Well, normally the recommendation would be that you should be able to rebuild your development image from scratch by loading your code from the repository. But if you had that, then the answer would be simple, just discard that image and reload. I think it's been long enough that I've lost whatever knowledge I've had about how to mess with the internal structures to get it back, and it sounds like you've tried a lot of things. So, although it might be painful, figuring out the recipe to rebuild your development image by loading stuff from the repository sounds like it may be your best bet. It probably isn't all that horrible, there just might be a few dependencies on the image state, or special doits that need to be executed.
You also probably need to validate what's in the repository against what's in the image you're working from. If there was unmanaged code loaded and then someone modified it and saved it, it's not clear to me that it would have been saved to ENVY. So you probably want to audit everything that was unmanaged code and if it's been changed, save that to a repository edition.
Sorry I don't have any better answers.