My app breaks when moved while running
-
Hello,
A while ago I submitted a bug report to Apple that my app broke
when the user moved it around in the Finder while it was running. I
was told by Apple to "use the bundle APIs correctly". So, now 5
years later, I'm looking in to it.
I have a very simple Cocoa app with a window in a nib with a static
PNG in the window (inside an NSImageView).
I create the window with:
[[NibClass alloc] initWithWindowNibName: @"NibName"];
When I move the app while it's running, and create the window
again, Cocoa is all confused and can't find the image referenced by
the Nib. And not just images, it can't find localized strings and
other important doodads in the App bundle.
So, what's the proper way to handle this so I can "use the bundle
APIs correctly"? Is there some way to inform Cocoa that my app has
moved?
Thanks,
Sanford
PS - The 10.5.1 Finder did not warn me when I moved my app while it
was running. -
I could be mistaken but I don't think there's a good mechanism to do
this. You should probably file a bug against the Finder for allowing
the user to do this without at least warning them that they should
quit the application before moving/renaming it (but even this would
still only be a partial solution: what if the user renamed a directory
in the path to the executable or moved their apps directory somewhere
else while running?) It seems like it would be a significant amount
of effort, both in the Apple frameworks and for app developers, to
keep a non-trivial application functioning properly to being moved/
renamed while running vs. what percentage of users would ever attempt
to do this even once.
Phil
On Feb 7, 2008, at 2:50 PM, Sanford Selznick wrote:
> Hello,
>
> A while ago I submitted a bug report to Apple that my app broke
> when the user moved it around in the Finder while it was running. I
> was told by Apple to "use the bundle APIs correctly". So, now 5
> years later, I'm looking in to it.
>
> I have a very simple Cocoa app with a window in a nib with a static
> PNG in the window (inside an NSImageView).
>
> I create the window with:
>
> [[NibClass alloc] initWithWindowNibName: @"NibName"];
>
> When I move the app while it's running, and create the window
> again, Cocoa is all confused and can't find the image referenced by
> the Nib. And not just images, it can't find localized strings and
> other important doodads in the App bundle.
>
> So, what's the proper way to handle this so I can "use the bundle
> APIs correctly"? Is there some way to inform Cocoa that my app has
> moved?
>
> Thanks,
> Sanford
>
> PS - The 10.5.1 Finder did not warn me when I moved my app while it
> was running.
-
If this is a real app and not just something you are doing for your
own edification, seriously consider the cost vs benefits of this "move
around feature." I can't see benefit and the furl (file url), fullpath
system that is shot throughout Cocoa makes it a very expensive
proposition. I faced a slightly similar issue doing dynamic net
upgrades of an app. There is an solution based on storing your app's
current location as an alias, then checking for changes before you go
to disk for a furl-specified resource, but I wouldn't wish it on anyone. -
If there is major concern that a user will be moving the app around while it
is running, why don't you store the static .png in the Application Support
folder for your program (~/Library/Application Support/your_app/)? This is
what Apple recommends when you need to store and access application-specific
data other than preference files and the like.
Devon
On Feb 7, 2008 9:28 PM, William Bates <knowledgeengineering...> wrote:
> If this is a real app and not just something you are doing for your
> own edification, seriously consider the cost vs benefits of this "move
> around feature." I can't see benefit and the furl (file url), fullpath
> system that is shot throughout Cocoa makes it a very expensive
> proposition. I faced a slightly similar issue doing dynamic net
> upgrades of an app. There is an solution based on storing your app's
> current location as an alias, then checking for changes before you go
> to disk for a furl-specified resource, but I wouldn't wish it on anyone.
>
-
Phil wrote:
> I could be mistaken but I don't think there's a good mechanism to do
> this. You should probably file a bug against the Finder for allowing
> the user to do this without at least warning them that they should
> quit the application before moving/renaming it (but even this would
> still only be a partial solution: what if the user renamed a directory
> in the path to the executable or moved their apps directory somewhere
> else while running?) It seems like it would be a significant amount
> of effort, both in the Apple frameworks and for app developers, to
> keep a non-trivial application functioning properly to being moved/
> renamed while running vs. what percentage of users would ever attempt
> to do this even once.
While the raw effort *is* probably significant, the solution seems
fairly straightforward. Instead of relying on cached paths (or
whatever static structure is underlying these problems), the bundle
mechanisms could be caching aliases. Obviously there's not a
widespread habit among users of moving a running app, but it's
something that historically didn't inherently break anything. From a
little experimentation, it seems like there's no way to *not* break a
package-style app by moving it; among the "important doodads" that
can't be reliably retrieved are the nib files that would define other
windows, views, etc.
What I'd be worried about are UIElement-type apps. The things that
users tend to leave running over their entire session, some of which
do have discrete Finder icons (rather than being resources of a
prefPane or the like).
Actually, there *is* a workaround. Cache an alias to the main bundle
at launch time, and then go out of your way to never rely (explicitly
or implicitly) on the main bundle again. Instead, create a bundle for
the resolved alias any time you need to do anything.
G -
On 2/7/08 3:31 PM, Phil said:
> It seems like it would be a significant amount
> of effort, both in the Apple frameworks and for app developers, to
> keep a non-trivial application functioning properly to being moved/
> renamed while running vs. what percentage of users would ever attempt
> to do this even once.
You're thinking like a programmer. What percentage of users would even
consider that moving a running app could be a problem? Why should it
be? Many users don't even understand the whole idea of the file system
hierarchy, let alone such subtleties.
--
____________________________________________________________
Sean McBride, B. Eng <sean...>
Rogue Research www.rogue-research.com
Mac Software Developer Montréal, Québec, Canada -
On 8 Feb '08, at 4:42 AM, Gregory Weston wrote:
> While the raw effort *is* probably significant, the solution seems
> fairly straightforward. Instead of relying on cached paths (or
> whatever static structure is underlying these problems), the bundle
> mechanisms could be caching aliases.
That's a possibility. Aliases don't work on all types of filesystems,
though — IIRC, NFS is one that doesn't support them. SMB might be
another; I'm not sure.
There are significant numbers of Macs being used in enterprise /
higher-ed environments where apps or user accounts live on such file
servers. In the past, that's been given as a rationale for not adding
low-level OS features/improvements, such as this, that depend on
filesystem functionality that isn't universally available.
Another issue with caching aliases is that it's prone to race
conditions. At some point you have to dereference the alias into a
path, and then use the path. If the app moves in between those two
moments, the attempt to use the path will fail.
In an ideal world users should be able to move apps willy-nilly, but I
have to say I've never heard of a case where this actually caused a
problem in the real world. Moving documents is a lot more common, so
NSDocument does have support for tracking file movement.
—Jens -
On Feb 8, 2008 12:11 PM, Jens Alfke <jens...> wrote:
> Another issue with caching aliases is that it's prone to race
> conditions. At some point you have to dereference the alias into a
> path, and then use the path. If the app moves in between those two
> moments, the attempt to use the path will fail.
Alias records since 10.3 (I think) dereference based on path
heuristics first, and then fall back on attribute matching. While not
immune to the race condition (call to dereference, block on IO, get
scheduled off processor, file moves and is truncated or something, get
scheduled back on processor and begin executing) it's at least a bit
more resilient.
--Kyle Sluder -
On Feb 8, 2008, at 10:37 AM, Sean McBride wrote:
> On 2/7/08 3:31 PM, Phil said:
>
>> It seems like it would be a significant amount
>> of effort, both in the Apple frameworks and for app developers, to
>> keep a non-trivial application functioning properly to being moved/
>> renamed while running vs. what percentage of users would ever attempt
>> to do this even once.
>
> You're thinking like a programmer. What percentage of users would
> even
> consider that moving a running app could be a problem? Why should it
> be? Many users don't even understand the whole idea of the file
> system
> hierarchy, let alone such subtleties.
Actually I was thinking about it from a user, customer support, and
business standpoint. When I think about scenarios I've dealt with on
my own or in supporting others and this scenario has never come up.
Granted, there are a great many things that users aren't aware of (nor
should they need to be) and I was making the point that it seemed like
a lot of work for a relatively small payback. I just checked several
apps from Apple and 3rd parties and none that I tried works correctly
in this scenario. Anyway, Sanford has users reporting this problem
and he's trying to find a solution which makes perfect sense to me.
Thanks,
Phil -
There's no obligation to empower users to shoot themselves in the
foot.
If real users were/are actually moving your app around [it's not clear
if this is a real-world problem or a hypothetical] an approach, not
mentioned yet, is to try to detect the situation, provide a warning if
possible, and die.
Once upon a time small programs could be memory resident. You could
do anything you liked to their file, including delete it, and the app
would run until termination. Its code was loaded. Today any non-
trivial app need access to disk-based resources and much of Cocoa and
Carbon are a set of conventions about how to get them. If you want the
ease of using constructs like "initWithWindowNibName: @"NibName"];"
you gotta play by the implied rules. You can pre-load all your images
and nibs into memory; you might get by. And if not, remember that
system error alerts (I'd look to the barest-bone Carbon alert) are
usually designed to rely on a bare minimum of disk resources and
display under really adverse circumstances. -
There's a potential enhancement here for Mac OS X, where the operating
system locks the application file as part of the activation sequence. -
(Previous message was incomplete. Please ignore.)
There is the potential here for a enhancement to Mac OS X, where the
application files are locked as part of invoking the application. This
sort of transparent and distributed locking is comparatively rare in
Unix environments, but there are operating systems where this locking
does occur.
Various attempts include:
http://freshmeat.net/projects/dlm/
http://opendlm.sourceforge.net/
Basically, the application activation would lock down the file(s) (or
bundle) associated with the application, preventing modifications.
Some form of locking is likely present in the Xsan file system support,
I'm not sufficiently familiar with that to post a reference.
I'd have to say that this particular sequence and this locking would be
rather low on my list of application priorities. It's in the "if it
hurts, don't do it" category. And yes, we do all have to deal with the
sheer creativity of our user base. And once in a while, such creativity
will cause the application to tip over.



