Normally an application bundle on OS X can only be started once, however by simply copying the bundle the same application can be launched twice. What's the best strategy to detect and stop this possibility?
On Windows this effect can simply be achieved by the application creating a named resource at launch and then exit if the named resource can't be created, indicating that another process is running that has already created the same resource. These resources are released in a reliable way on Windows when the application quits.
The problem I have seen when researching this is that the APIs on OS X keep state in the file system and thus makes the strategy used on windows unreliable, i.e lingering files after an improper exit can falsely indicate that the application is already running.
The APIs I can use to achieve the same effect on OS X are: posix, carbon and boost.
Ideas?
A low-level solution is to use flock().
Each instance would attempt to lock a file on startup, and if the lock fails then another instance is already running. Flocks are automagically released when your program exits, so no worries about stale locks.
Note that whatever solution you choose, you need to make a conscious decision about what it means to have "multiple instances". Specifically, if multiple users are running your app at the same time, is that ok?
detect if application with same bundleID is running, activate it and close what starts.
First off, it's “Mac OS X” or “OS X”. There is no such thing as “OS/X”.
Second, Mac OS X doesn't come with Boost; you would need to bundle it with your application.
Third, most of Carbon is not available in 64-bit. This is a clear signal that those portions of Carbon will go away someday (when Apple abandons 32-bit in its hardware). Sooner or later, you will have to either rewrite your app with Cocoa or abandon the Mac.
No it can't. Launching the renamed or moved application will simply activate (bring to the front) the process that was already running; it won't start a new, second process alongside the first one.
There are several ways to tell whether an application is already running. In each case, you do this on launch:
If you're looking to see when someone runs a second copy of yourself, you can use CFNotificationCenter:
In your observation callback for the Call notification, post the Response notification.
In your observation callback for the Response notification, exit.
Thus, when the first process starts, it will Call and get no Response; when the second process starts, it will Call, get a Response from the first process, and exit in deference to the first.
This is a combination of Romans' and Jeff's answers for Swift 2.0: If another instance of the app with the same bundle ID is already running, show an alert, activate the other instance and quit the duplicate instance.
This is extremely easy in Snow Leopard:
See http://blog.jseibert.com/post/1167439217/deduplicating-running-instances-or-how-to-detect-if for more information.
There's a mysterious Info.plist key called "Application prohibits multiple instances," but it doesn't seem to work for me. I am writing a CLI application and executing it from within a bundle. Perhaps it would work in a GUI application, but I haven't tried.