Non-AppKit equivalent for NSWorkspace and/or future-proof poseAsClass?

  • G'Day!

    I'm trying to write an application in two parts: a client GUI and a
    faceless "agent" (launched by launchd), communicating via Distributed
    Objects. This all works.

    Among other things, I want the agent to respond to notifications sent by
    NSWorkspace (like NSWorkspaceDidLaunchApplicationNotification,
    NSWorkspaceDidMountNotification, and friends). This all works too.

    The problem occurs when I try to make the the agent a proper agent (ie,
    launched by launchd).

    The property list has LSBackgroundOnly=1 and LSUIElement=1 (I've also
    experimented with LSUIPresentationMode=4).

    Early on I found that trying to build the agent without any nibs caused the
    thing to barf, so I used a dummy MainMenu.nib. After that, the agent would
    launch properly and behave correctly most of the time. But, very
    occasionally, it would get into a loop where it would abort during launch,
    after which launchd would promptly restart it, repeat, with serious
    consumption of CPU cycles until launchd gave up. The console log always had
    the same message for each crash:

    "Window Server communications from outside of session allowed for
    root and console user only"

    and the first part of the crash dump always had:

    Exception:  EXC_BREAKPOINT (0x0006)
    Code[0]:    0x00000002
    Code[1]:    0x00000000

    Thread 0 Crashed:
    0  com.apple.Foundation        0x9282845f _NSRaiseError + 227
    1  com.apple.Foundation        0x9284f247 +[NSException
    raise:format:] + 57
    2  com.apple.AppKit            0x9329ea00 +[NSScreen screens] + 191
    3  com.apple.AppKit            0x9329e920 +[NSScreen _zeroScreen] + 36
    4  com.apple.AppKit            0x9329cfd4 -[NSWindowTemplate
    nibInstantiate] + 181
    5  com.apple.AppKit            0x93284e30 -[NSIBObjectData
    instantiateObject:] + 232
    6  com.apple.AppKit            0x93284379 -[NSIBObjectData
    nibInstantiateWithOwner:topLevelObjects:] + 202
    7  com.apple.AppKit            0x9327b9ad loadNib + 260
    8  com.apple.AppKit            0x9327b3d9 +[NSBundle(NSNibLoading)
    _loadNibFile:nameTable:withZone:ownerBundle:] + 918
    9  com.apple.AppKit            0x9327b03a +[NSBundle(NSNibLoading)
    loadNibFile:externalNameTable:withZone:] + 164
    10  com.apple.AppKit            0x9327af7c +[NSBundle(NSNibLoading)
    loadNibNamed:owner:] + 392
    11  com.apple.AppKit            0x9327acc3 NSApplicationMain + 433
    12  com.lgosys.TestServer  0x0000212a _start + 216
    13  com.lgosys.TestServer  0x00002051 start + 41

    I've dealt with this by defining a small private class which includes the
    class method:

    +(BOOL) loadNibNamed:(NSString*)aNibNamed owner:(id)owner
    {
           return YES;
    }

    and then sticking the following at the beginning of main.m:

    [[MyClass class] poseAsClass:[NSBundle class]];

    That (a) allows me to build without any nibs in the bundle and (b) appears
    to cure the crash on launch. All other things being equal, my problem would
    seem to be solved. However, I'm not overly happy with this as a solution.
    For one thing, poseAsClass is now deprecated so it isn't really a long-term
    answer.

    The underlying problem, really, is that I'm having to load AppKit just to
    get NSWorkspace. That's the *only* thing I need from AppKit.

    So, I have two questions:

    1. Can I get the same NSWorkspace notifications from somewhere else? I've
    nosed through /System/Library/Frameworks without stumbling across anything
    obvious but I may just be blind.

    2. Does anyone happen to know if there is an equivalent for the poseAsClass
    mechanism (or can suggest an alternative approach that will keep AppKit
    happy)?

    Regards & thanks,  PK
  • On Jan 9, 2008, at 6:59 AM, Phill Kelley wrote:

    > 1. Can I get the same NSWorkspace notifications from somewhere
    > else? I've
    > nosed through /System/Library/Frameworks without stumbling across
    > anything
    > obvious but I may just be blind.
    >

    You should be able to get the notifications from elsewhere, but they
    might not necessary all be wrapped up nicely in the same framework.
    For example, you can get mount and unmount notifications from /System/
    Library/Frameworks/DiskArbitration.framework.

    > 2. Does anyone happen to know if there is an equivalent for the
    > poseAsClass
    > mechanism (or can suggest an alternative approach that will keep
    > AppKit
    > happy)?
    >

    Yes, take a look at my article at <http://lapcatsoftware.com/blog/
    2007/11/25/working-without-a-nib-part-6-working-without-a-xib/
    >.

    -Jeff
  • Il giorno 09/gen/08, alle ore 13:59, Phill Kelley ha scritto:

    > I'm trying to write an application in two parts: a client GUI and a
    > faceless "agent" (launched by launchd), communicating via Distributed
    > Objects. This all works.

    You *are* using LimitLoadToSessionType = "Aqua" and requiring 10.5+,
    riiiiight?
    LaunchAgents may be launched at inappropriate times before 10.5 (that
    is, in sessions where a window manager connection can't be retrieved
    -- which makes more or less all of AppKit unusable). See Apple's
    Daemonomicon at <http://developer.apple.com/technotes/tn2005/
    tn2083.html
    > for more.

      - ∞
  • > Il giorno 09/gen/08, alle ore 13:59, Phill Kelley ha scritto:
    >
    >> I'm trying to write an application in two parts: a client GUI and a
    >> faceless "agent" (launched by launchd), communicating via Distributed
    >> Objects. This all works.
    >
    > You *are* using LimitLoadToSessionType = "Aqua" and requiring 10.5+,
    > riiiiight?

    No. I want this to be Tiger-compatible (at least for the next 12-24 months).

    In any event, I don't actually *want* GUI services in the agent so, of the
    permitted values listed in tn2083 for LimitLoadToSessionType, "Background"
    would seem more appropriate.

    The idea is that there is one instance of the agent running for each user
    logged into the machine. Apart from anything else, this strategy avoids
    having to worry about security issues or having to maintain so-called
    Chinese Walls between users, such as might arise if the agent was made a
    daemon instead.

    Each user *may* launch the foreground GUI to configure/inspect what the
    background agent is doing but the GUI itself does not need to be running
    for the agent to be able to do its thing.

    > LaunchAgents may be launched at inappropriate times before 10.5 (that
    > is, in sessions where a window manager connection can't be retrieved
    > -- which makes more or less all of AppKit unusable). See Apple's
    > Daemonomicon at < http://developer.apple.com/technotes/tn2005/
    >tn2083.html> for more.

    Thanks. I recall reading the earlier version of that tech note but the
    current version goes a long way towards explaining the intermittent nature
    of the launchd-associated launch-and-crash loop.

    The main reason I had focused on /Library/LaunchAgents as the mechanism for
    launching the agent was the neat way it deals with restarting in the event
    of a crash; something a login item doesn't get me for free. Naturally, I
    always hope to write crash-proof code but...

    Now I need to mull over the wisdom of this in a pre-Leopard environment.

    At 07:20 -0600 9/1/08, Jeff Johnson wrote:
    >> 2. Does anyone happen to know if there is an equivalent for the
    >> poseAsClass
    >> mechanism (or can suggest an alternative approach that will keep
    >> AppKit
    >> happy)?
    >>
    >
    > Yes, take a look at my article at < http://lapcatsoftware.com/blog/
    >2007/11/25/working-without-a-nib-part-6-working-without-a-xib/>.

    Brilliant! Ditto Jean-Daniel for pointing me at the MethodReplacement code.

    Thanks also to Matt, Sean & Ricky for the sub-thread suggesting Carbon as a
    workaround. I am always slightly wary of Carbon. I worked hard to remove
    all Carbon dependencies from my code so reintroducing it seems like a
    retrograde step. I realise that sounds like I'm sticking my fingers in my
    ears and refusing to consider a perfectly rational suggestion so I'll give
    it some more thought.

    Regards & thanks,  PK
previous month january 2008 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today