Accessing Shared Data from an App Extension and its Containing App
Explains file coordination issues when used by an app extension to access a container shared with its containing app.
Using file coordination in an app extension to access a container shared with its containing app may result in a deadlock in iOS versions 8.1.x and earlier. This is usually the case if a process is suspended mid coordinated I/O. This can be more prevalent on iOS where most apps will be suspended after a short period of time after being moved to the background. Extensions should use alternatives to file coordination. This has since been resolved in iOS 8.2.
Instead, use CFPreferences, atomic safe save operations on flat files, SQLite or Core Data.
File Coordination and Shared Containers
File coordination does not have a mechanism for handling process suspensions. On iOS, processes can be suspended as part of jetsam and process management. On OS X, this only happens in the debugger. The recommended practice on iOS 7, and for applications in general, is to handle the UIApplication notifications that the app has been backgrounded and cancel coordinated actions and remove file presenters. When the app is brought back to the foreground, the file presenters can be re-added. Extensions do not get UIApplication backgrounding notifications and cannot do that. Extensions also cannot take additional background task assertions, so they cannot avoid being suspended like applications.
You can use CFPreferences, atomic safe save operations on flat files, or SQLite or Core Data to share data in a group container between multiple processes even if one is suspended mid transaction. For SQLite/Core Data, processes using databases in DELETE journal mode will be instantly killed instead of suspended. Processes using database in WAL journal mode will only be jetsam'd if they attempt to hold a write transaction open at the time of suspension. Posix file locks also work, and behave similarly to SQLite database in DELETE journal mode, so open(O_EXLOCK) or flock() could also be used.
Regardless of this issue, the containing app (and all applications) should properly use background task assertions around file operations they require completed in a shared container (with or without extensions). This includes all writes or deletions. Such a process might still be killed by jetsam but at a much lower frequency.
Document Revision History
Updated to indicate workarounds only apply to iOS 8.1 and earlier, issue resolved in iOS 8.2 and later.
New document that explains file coordination issues when used by an app extension to access a container shared with its containing app.