Cross-user and cross-process shared settings

眉间皱痕 提交于 2019-12-11 09:47:52

问题


I have two processes - a user process and a root-level LaunchDaemon. I'd like both processes to have shared settings. I've tried getting this to work via a sqlite database, but have run into corruption issues. I've thought about using NSUserDefaults, but the NSGlobalDomain seems to only be global for the user, and I need a cross-user persistent domain, which NSUserDefaults doesn't seem to provide.

I've tried reading and writing an XML file directly, and I can get this to work fine with multiple threads (via a simple NSLock), but when I attempt to apply an O_EXLOCK to the file to prevent one process from writing to the file while the other is, it doesn't seem to work.

CFPreferences seems to have most of the same issues as NSUserDefaults. There is a kCFPreferencesAnyUser constant, but the documentation says that I can only use that if I have admin privileges (which the user process does not have).

So my question is this:

How can I effectively implement cross-process and cross-user shared settings?


回答1:


Your best bet is probably the O_EXLOCK approach, wrapped into an NSFileHandle for convenience (-initWithFileDescriptor:). Something like this (untested; uncompiled):

Writing:

int fd = open([path UTF8String], O_TRUNC|O_EXLOCK);
if (fd >= 0)
{
    NSFileHandle *fh = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES];
    [fh writeData:xmlData]; // Creating xmlData left as exercise for the reader
    [fh release];
}
else // Error stuff

Reading:

int fd = open([path UTF8String], O_RDONLY|O_SHLOCK);
if (fd >= 0)
{
    NSFileHandle *fh = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES];
    NSData *xmlData = [fh readDataToEndOfFile];
    [fh release];
}
else // Error stuff

Of course these will block, so you need to use O_NONBLOCK or put them on a non-UI thread so your GUI app doesn't beachball.

What's the problem you're seeing with O_EXLOCK?




回答2:


Note that using O_EXLOCK and O_SHLOCK with open(2) just lets you avoid a call to flock(2). Mac OS X only supports advisory locking, and, as the manpage for flock() notes:

Advisory locks allow cooperating processes to perform consistent operations on files, but do not guarantee consistency (i.e., processes may still access files without using advisory locks possibly resulting in inconsistencies).

You'll run into problems, then, if both apps are not opting into the advisory locking system every time they open the advisory-locked file.

You could also try having the user process make defaults calls via the daemon using RPC. It would then handle all default writing on behalf of client applications; default reading would already hit the any user, current host/any host defaults.



来源:https://stackoverflow.com/questions/1337761/cross-user-and-cross-process-shared-settings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!