detecting when an app is beach-balling

  • is there any easy way to programmatically detect when another app is
    beachballing?

      I was hoping that there might be some kind of no-op Apple Event
    that I could despatch to it, to see whether I get a reply or not, but
    I can't spot anything in the docs ...

        cheers,
            Martin
  • Thanks. That looks like it would work for scriptable apps (although I
    haven't tried it against a beachballer), but not for non-scriptable
    ones.

    Spin Control doesn't seem to do any polling - it just seems to be
    waiting for a callback or notification of some kind - presumably
    that's in some private API.

    On 20 Oct 2007, at 18:34, Emanuele ° Vulcano wrote:

    >
    > Il giorno 20/ott/07, alle ore 17:35, Martin Redington ha scritto:
    >
    >> I was hoping that there might be some kind of no-op Apple Event
    >> that I could despatch to it, to see whether I get a reply or not,
    >> but I can't spot anything in the docs ...
    >
    > There is certainly one -- the one that is dispatched by AppleScript
    > when you tell app "SomeApp" to run.
    >
    > - °

    AE2000 (1058): Sending an event:
    ------oo start of event oo------
    { 1 } 'aevt':  ascr/gdte (i386){
              return id: 69337094 (0x4220006)
          transaction id: 0 (0x0)
      interaction level: 64 (0x40)
          reply required: 1 (0x1)
                  remote: 0 (0x0)
          for recording: 0 (0x0)
      target:
        { 2 } 'psn ':  8 bytes {
          { 0x0, 0x4600001 } (Address Book)
        }
      fEventSourcePSN: { 0x0,0x45e0001 } (osascript)
      optional attributes:
        < empty record >
      event data:
        { 1 } 'aevt':  - 1 items {
          key '----' -
            { 1 } 'long':  4 bytes {
              0 (0x0)
            }
        }
    }
  • Just to clarify,

    -- begin AppleScript
    tell application "AnyApplication"
    activate
    end
    -- end AppleScript

    will start up any app, whether it's scriptable or not.  Of course,
    you have to name your target app properly, that is, substitute a real
    name for "AnyApplication".

    Ron

    On 22/10/2007, at 7:59 PM, Martin Redington wrote:

    >
    > Thanks. That looks like it would work for scriptable apps (although
    > I haven't tried it against a beachballer), but not for non-
    > scriptable ones.
    >
    > Spin Control doesn't seem to do any polling - it just seems to be
    > waiting for a callback or notification of some kind - presumably
    > that's in some private API.
    >
    >
    > On 20 Oct 2007, at 18:34, Emanuele ° Vulcano wrote:
    >
    >>
    >> Il giorno 20/ott/07, alle ore 17:35, Martin Redington ha scritto:
    >>
    >>> I was hoping that there might be some kind of no-op Apple Event
    >>> that I could despatch to it, to see whether I get a reply or not,
    >>> but I can't spot anything in the docs ...
    >>
    >> There is certainly one -- the one that is dispatched by
    >> AppleScript when you tell app "SomeApp" to run.
    >>
    >> - °
    >
    > AE2000 (1058): Sending an event:
    > ------oo start of event oo------
    > { 1 } 'aevt':  ascr/gdte (i386){
    > return id: 69337094 (0x4220006)
    > transaction id: 0 (0x0)
    > interaction level: 64 (0x40)
    > reply required: 1 (0x1)
    > remote: 0 (0x0)
    > for recording: 0 (0x0)
    > target:
    > { 2 } 'psn ':  8 bytes {
    > { 0x0, 0x4600001 } (Address Book)
    > }
    > fEventSourcePSN: { 0x0,0x45e0001 } (osascript)
    > optional attributes:
    > < empty record >
    > event data:
    > { 1 } 'aevt':  - 1 items {
    > key '----' -
    > { 1 } 'long':  4 bytes {
    > 0 (0x0)
    > }
    > }
    > }
  • yep, that wil send a misc/actv event to the app, and activate it
    (starting it if its not started already, or bringing it to the front
    otherwise).

    I don't actually want to activate it though - just to see if its
    spinning (on the assumption that if it replies to an event, its not
    spinning).

    ascr/gdte seems to do what I want for running apps, but not for non-
    scriptable apps (I'm presuming that I'll only be polling running apps).

    On 22 Oct 2007, at 11:38, Ron Fleckner wrote:

    > Just to clarify,
    >
    > -- begin AppleScript
    > tell application "AnyApplication"
    > activate
    > end
    > -- end AppleScript
    >
    > will start up any app, whether it's scriptable or not.  Of course,
    > you have to name your target app properly, that is, substitute a
    > real name for "AnyApplication".
    >
    > Ron
    >
    >
    > On 22/10/2007, at 7:59 PM, Martin Redington wrote:
    >
    >>
    >> Thanks. That looks like it would work for scriptable apps
    >> (although I haven't tried it against a beachballer), but not for
    >> non-scriptable ones.
    >>
    >> Spin Control doesn't seem to do any polling - it just seems to be
    >> waiting for a callback or notification of some kind - presumably
    >> that's in some private API.
    >>
    >>
    >> On 20 Oct 2007, at 18:34, Emanuele ° Vulcano wrote:
    >>
    >>>
    >>> Il giorno 20/ott/07, alle ore 17:35, Martin Redington ha scritto:
    >>>
    >>>> I was hoping that there might be some kind of no-op Apple Event
    >>>> that I could despatch to it, to see whether I get a reply or
    >>>> not, but I can't spot anything in the docs ...
    >>>
    >>> There is certainly one -- the one that is dispatched by
    >>> AppleScript when you tell app "SomeApp" to run.
    >>>
    >>> - °
    >>
    >> AE2000 (1058): Sending an event:
    >> ------oo start of event oo------
    >> { 1 } 'aevt':  ascr/gdte (i386){
    >> return id: 69337094 (0x4220006)
    >> transaction id: 0 (0x0)
    >> interaction level: 64 (0x40)
    >> reply required: 1 (0x1)
    >> remote: 0 (0x0)
    >> for recording: 0 (0x0)
    >> target:
    >> { 2 } 'psn ':  8 bytes {
    >> { 0x0, 0x4600001 } (Address Book)
    >> }
    >> fEventSourcePSN: { 0x0,0x45e0001 } (osascript)
    >> optional attributes:
    >> < empty record >
    >> event data:
    >> { 1 } 'aevt':  - 1 items {
    >> key '----' -
    >> { 1 } 'long':  4 bytes {
    >> 0 (0x0)
    >> }
    >> }
    >> }
    >
  • Martin Redington wrote:

    > yep, that wil send a misc/actv event to the app, and activate it

    miscactv (activate) = bring to front, so you don't really want to use
    that.

    > (starting it if its not started already, or bringing it to the front
    > otherwise).

    Note that application launching is unrelated to Apple events. The
    Apple Event Manager is not able to launch applications itself.
    AppleScript automatically launches a non-running application by
    calling the Carbon Process Manager's LaunchApplication() (there's
    also LaunchServices' LSLaunchApplication() in 10.4+).

    > ascr/gdte seems to do what I want for running apps, but not for non-
    > scriptable apps (I'm presuming that I'll only be polling running
    > apps).

    'ascrgdte' = 'get dynamic AppleScript terminology'. It will work for
    any application as the OS provides a default ascrgdte event handler
    that calls through to OSAGetAppTerminology. If an application doesn't
    have a terminology resource, the reply event will contain a 'resource
    not found' error (-192).

    Ron Fleckner wrote:

    > -- begin AppleScript
    > [...]
    > -- end AppleScript
    >
    > will start up any app, whether it's scriptable or not.  Of course,
    > you have to name your target app properly, that is, substitute a
    > real name for "AnyApplication".

    Those would be two pretty good reasons to avoid using the AppleScript
    language. You probably don't want the application being launched
    automatically if it isn't already running, and you definitely don't
    want one of those wretched 'Where is application...?' dialogs
    appearing if AppleScript can't immediately locate the application in
    question. A third reason would be if you wanted to perform this test
    from a non-main thread, for which AppleScript is teh suck.

    Anyway, the standard 'no-op' event is ascrnoop. The AppleScript
    equivalent is 'tell app "Foo" to launch', with the caveat that
    AppleScript treats this command as a special case and always sends it
    with a kAENoReply flag. That's no good if you're wanting to wait for
    a reply event, but it's a non-issue if you send the event via another
    method.

    Assuming you don't tell the Apple Event Manager to wait forever for a
    reply event (you can specify the timeout delay when you send the
    event), what you're looking for is an 'event timed out' error (-1712)
    returned by AESend()/AESendMessage() to tell you if the application
    (specifically its main thread) is busy, or 'no error' (0) to tell you
    that the event was received and responded to (you'll also get a reply
    event containing an 'event not recognised' error, -1708, which you
    can just ignore).

    To build and send your event, you could use objc-appscript's AEM API
    (which provides a convenient ObjC wrapper around the Apple Event
    Manager API) to send the relevant event, or it's a simple enough task
    that you could do pack and send the event yourself using
    NSAppleEventDescriptor and AESendMessage. If you need example code,
    just ask.

    HTH (and touch-wood I got that all correct...)

    has
    --
    http://appscript.sourceforge.net
    http://rb-appscript.rubyforge.org
  • Thankyou to everyone who's posted in reply to my query.

    It looks like there probably is a route to doing what I want (testing
    if the app is processing Apple events) via AppleScript, but it also
    looks as though there is a probably more efficient route being
    utilised by Spin Control and Activity Monitor.

    Any pointers to that mechanism would be great ...

        cheers,
                m.

    On 22 Oct 2007, at 18:01, has wrote:

    > Martin Redington wrote:
    >
    >> yep, that wil send a misc/actv event to the app, and activate it
    >
    > miscactv (activate) = bring to front, so you don't really want to
    > use that.
    >
    >
    >> (starting it if its not started already, or bringing it to the front
    >> otherwise).
    >
    > Note that application launching is unrelated to Apple events. The
    > Apple Event Manager is not able to launch applications itself.
    > AppleScript automatically launches a non-running application by
    > calling the Carbon Process Manager's LaunchApplication() (there's
    > also LaunchServices' LSLaunchApplication() in 10.4+).
    >
    >
    >> ascr/gdte seems to do what I want for running apps, but not for non-
    >> scriptable apps (I'm presuming that I'll only be polling running
    >> apps).
    >
    > 'ascrgdte' = 'get dynamic AppleScript terminology'. It will work
    > for any application as the OS provides a default ascrgdte event
    > handler that calls through to OSAGetAppTerminology. If an
    > application doesn't have a terminology resource, the reply event
    > will contain a 'resource not found' error (-192).
    >
    >
    > Ron Fleckner wrote:
    >
    >> -- begin AppleScript
    >> [...]
    >> -- end AppleScript
    >>
    >> will start up any app, whether it's scriptable or not.  Of course,
    >> you have to name your target app properly, that is, substitute a
    >> real name for "AnyApplication".
    >
    > Those would be two pretty good reasons to avoid using the
    > AppleScript language. You probably don't want the application being
    > launched automatically if it isn't already running, and you
    > definitely don't want one of those wretched 'Where is
    > application...?' dialogs appearing if AppleScript can't immediately
    > locate the application in question. A third reason would be if you
    > wanted to perform this test from a non-main thread, for which
    > AppleScript is teh suck.
    >
    >
    > Anyway, the standard 'no-op' event is ascrnoop. The AppleScript
    > equivalent is 'tell app "Foo" to launch', with the caveat that
    > AppleScript treats this command as a special case and always sends
    > it with a kAENoReply flag. That's no good if you're wanting to wait
    > for a reply event, but it's a non-issue if you send the event via
    > another method.
    >
    > Assuming you don't tell the Apple Event Manager to wait forever for
    > a reply event (you can specify the timeout delay when you send the
    > event), what you're looking for is an 'event timed out' error
    > (-1712) returned by AESend()/AESendMessage() to tell you if the
    > application (specifically its main thread) is busy, or 'no
    > error' (0) to tell you that the event was received and responded to
    > (you'll also get a reply event containing an 'event not recognised'
    > error, -1708, which you can just ignore).
    >
    > To build and send your event, you could use objc-appscript's AEM
    > API (which provides a convenient ObjC wrapper around the Apple
    > Event Manager API) to send the relevant event, or it's a simple
    > enough task that you could do pack and send the event yourself
    > using NSAppleEventDescriptor and AESendMessage. If you need example
    > code, just ask.
    >
    >
    > HTH (and touch-wood I got that all correct...)
    >
    > has
    > --
    > http://appscript.sourceforge.net
    > http://rb-appscript.rubyforge.org
    >
    >
  • Hmmm, this all has me wondering if Apple & Intel engineers are (or
    should be) listening in on this thread. In embedded-systems design,
    many (if not all) micro-controllers have a WDT (Watch Dog Timer) that
    will reset the micro-controller if it hangs (gets in an infinite
    loop). While such would be useless by itself, it would be handy if a
    (new) processor (Intel Core 3 Duo, anyone? or an 8-core Xeon) could
    "attach" a WDT to a thread with a programmable delay (ideally stored
    in a 64-bit special-purpose register, indexed by thread). "ordinary"
    threads could be given a "reasonable" delay by OS X, while
    computation-intensive threads could be given the longest delay
    possible so that the thread wouldn't be stopped prematurely by the
    WDT. Of course, this would require an API so those doing scientific
    research on OS X with Xcode/Cocoa could give their computation
    threads a greater delay. Maybe via NSWorkspace?
      Still, using only software, I'm not sure you can do this as any
    app/process/thread that hangs will also hang any process that tries
    to determine its state, unless is has a timeout (like the WDT above)
    or a pattern-recognition algorithm which would say "hey, the current
    state of thread N is significantly different/same than the last X
    samples of the thread execution."
      IIRC, this is related to the "stopping" theory put forth by early
    pioneers in computing that stated (roughly) that you couldn't prove -
    using a system of logic or mathematics - that a computer program
    would ever terminate (unless it was trivially simple.)
      Just my $0.02.

    On Oct 22, 2007, at 12:01 PM, has wrote:

    > Martin Redington wrote:
    >
    >> yep, that wil send a misc/actv event to the app, and activate it
    >
    > miscactv (activate) = bring to front, so you don't really want to
    > use that.
    >
    >
    >> (starting it if its not started already, or bringing it to the front
    >> otherwise).
    >
    > Note that application launching is unrelated to Apple events. The
    > Apple Event Manager is not able to launch applications itself.
    > AppleScript automatically launches a non-running application by
    > calling the Carbon Process Manager's LaunchApplication() (there's
    > also LaunchServices' LSLaunchApplication() in 10.4+).
    >
    >
    >> ascr/gdte seems to do what I want for running apps, but not for non-
    >> scriptable apps (I'm presuming that I'll only be polling running
    >> apps).
    >
    > 'ascrgdte' = 'get dynamic AppleScript terminology'. It will work
    > for any application as the OS provides a default ascrgdte event
    > handler that calls through to OSAGetAppTerminology. If an
    > application doesn't have a terminology resource, the reply event
    > will contain a 'resource not found' error (-192).
    >
    >
    > Ron Fleckner wrote:
    >
    >> -- begin AppleScript
    >> [...]
    >> -- end AppleScript
    >>
    >> will start up any app, whether it's scriptable or not.  Of course,
    >> you have to name your target app properly, that is, substitute a
    >> real name for "AnyApplication".
    >
    > Those would be two pretty good reasons to avoid using the
    > AppleScript language. You probably don't want the application being
    > launched automatically if it isn't already running, and you
    > definitely don't want one of those wretched 'Where is
    > application...?' dialogs appearing if AppleScript can't immediately
    > locate the application in question. A third reason would be if you
    > wanted to perform this test from a non-main thread, for which
    > AppleScript is teh suck.
    >
    >
    > Anyway, the standard 'no-op' event is ascrnoop. The AppleScript
    > equivalent is 'tell app "Foo" to launch', with the caveat that
    > AppleScript treats this command as a special case and always sends
    > it with a kAENoReply flag. That's no good if you're wanting to wait
    > for a reply event, but it's a non-issue if you send the event via
    > another method.
    >
    > Assuming you don't tell the Apple Event Manager to wait forever for
    > a reply event (you can specify the timeout delay when you send the
    > event), what you're looking for is an 'event timed out' error
    > (-1712) returned by AESend()/AESendMessage() to tell you if the
    > application (specifically its main thread) is busy, or 'no
    > error' (0) to tell you that the event was received and responded to
    > (you'll also get a reply event containing an 'event not recognised'
    > error, -1708, which you can just ignore).
    >
    > To build and send your event, you could use objc-appscript's AEM
    > API (which provides a convenient ObjC wrapper around the Apple
    > Event Manager API) to send the relevant event, or it's a simple
    > enough task that you could do pack and send the event yourself
    > using NSAppleEventDescriptor and AESendMessage. If you need example
    > code, just ask.
    >
    >
    > HTH (and touch-wood I got that all correct...)
    >
    > has
    > --
    > http://appscript.sourceforge.net
    > http://rb-appscript.rubyforge.org
  • Unlike many embedded systems, all Mac OS X threads are
    preemptively scheduled.  That effectively means that
    no thread can monopolize the CPU.  All threads are
    periodically suspended/preempted so that other threads
    can run.  Watch dog timers are generally not involved.

    There are standard Unix real-time extensions:
    Functions like rtprio() enable you to set the relative
    priority of threads or processes so that they will be
    preempted less or more.

    There are also POSIX processor sets (pset_create())
    that enable you to specify which threads can run on
    which processors in multi-processor systems.  If you
    disable interrupts on a processor and set up a system
    so that the only thread that can run on the particular
    processor (or core) is your thread, your thread will
    not be preempted.  That is the only way to solve hard
    real time problems on a Unix system.

    The halting problem is irrelevant to these issues.

    I believe the Mac OS X window server periodically
    sends events to the event queue of all applications
    that have a connection to the window server.  If an
    application does not remove the event from its queue,
    the window server changes the cursor to the beach ball
    automatically.  The only thing the beach ball means is
    that an application is not taking events out of its
    queue fast enough.

    Again, the halting problem is irrelevant to these
    issues.  It is true that an application that is in an
    infinite loop will beach ball, but a perfectly healthy
    application that isn't taking events out of it's queue
    will also beach ball.

    > From an application's perspective, the Unix select()
    function is presumably called from the run loop and
    used to block the calling thread unless at least one
    input source (included in the select() call) has
    pending input.  The window server's event queue is
    just one input source for select().  Timers,
    distributed messages, apple events, distributed
    notifications, and any file descriptors you add are
    included in the select().
  • There is one very important point you should think about: How to
    recognise a finite loop from an infinite loop?
    It seems this problem IS the "Halting Problem", therefore it's an
    undecidable problem. Sure this can be a human decidable problem, but
    machine can't and won't.

    Really, how would a machine do? based on assumptions? A loop that
    lasts more than n is considered infinite? or on processor state changes?
    Furthermore, an infinite loop can be sane. Isn't the processor
    scheduler looping infinitely over processes to schedule? I mean,
    while not told to stop an operating system is supposed to run forever.

    So an application that's not responding to events has only stopped to
    do so, and you can't tell anything else. So it's finally up to the
    user to decide to wait till is finally responds again, or kill it.
    It's just as if in the terminal, you'd launch a program that takes
    some time and then the system would print out 'I've waited the
    termination for too long, I'm bailing out'.

    Regards.

    On Oct 23, 2007, at 4:17 AM, William Squires wrote:

    > Hmmm, this all has me wondering if Apple & Intel engineers are
    > (or should be) listening in on this thread. In embedded-systems
    > design, many (if not all) micro-controllers have a WDT (Watch Dog
    > Timer) that will reset the micro-controller if it hangs (gets in an
    > infinite loop). While such would be useless by itself, it would be
    > handy if a (new) processor (Intel Core 3 Duo, anyone? or an 8-core
    > Xeon) could "attach" a WDT to a thread with a programmable delay
    > (ideally stored in a 64-bit special-purpose register, indexed by
    > thread). "ordinary" threads could be given a "reasonable" delay by
    > OS X, while computation-intensive threads could be given the
    > longest delay possible so that the thread wouldn't be stopped
    > prematurely by the WDT. Of course, this would require an API so
    > those doing scientific research on OS X with Xcode/Cocoa could give
    > their computation threads a greater delay. Maybe via NSWorkspace?
    > Still, using only software, I'm not sure you can do this as any
    > app/process/thread that hangs will also hang any process that tries
    > to determine its state, unless is has a timeout (like the WDT
    > above) or a pattern-recognition algorithm which would say "hey, the
    > current state of thread N is significantly different/same than the
    > last X samples of the thread execution."
    > IIRC, this is related to the "stopping" theory put forth by early
    > pioneers in computing that stated (roughly) that you couldn't prove
    > - using a system of logic or mathematics - that a computer program
    > would ever terminate (unless it was trivially simple.)
    > Just my $0.02.
    >
    >
  • On 23 Oct 2007, at 03:47, Erik Buck wrote:

    > Unlike many embedded systems, all Mac OS X threads are preemptively
    > scheduled.  That effectively means that no thread can monopolize
    > the CPU.  All threads are periodically suspended/preempted so that
    > other threads can run.  Watch dog timers are generally not involved.

    Except in as much as the preemption is generally performed by way of
    a hardware interrupt from a system timer of some description.

    > There are standard Unix real-time extensions:  Functions like rtprio
    > () enable you to set the relative
    > priority of threads or processes so that they will be preempted
    > less or more.

    FYI, OS X has:

      nice()
      setpriority()
      pthread_get/setschedparam()
      pthread_attr_get/setschedparam()
      pthread_attr_get/setschedpolicy()
      Various Mach calls

    Not to mention, since this is after all the Cocoa developer list,
    NSThread's +setThreadPriority: method.

    > There are also POSIX processor sets (pset_create()) that enable you
    > to specify which threads can run on which processors in multi-
    > processor systems.  If you disable interrupts on a processor and
    > set up a system so that the only thread that can run on the
    > particular processor (or core) is your thread, your thread will not
    > be preempted.  That is the only way to solve hard real time
    > problems on a Unix system.

    Well it rather depends on the problem, the system, and what you
    consider to be acceptable failure modes. A number of tasks that used
    to be regarded as hard real-time (audio, for instance) are now
    generally held to be soft real-time because the performance of
    systems has increased so much that the maximum likely delay is now
    acceptable whereas previously it wouldn't have been.  There are also
    special features in some systems (LynxOS being perhaps the primary
    example) to enable hard real-time performance.

    > I believe the Mac OS X window server periodically sends events to
    > the event queue of all applications
    > that have a connection to the window server.  If an application
    > does not remove the event from its queue, the window server changes
    > the cursor to the beach ball automatically.  The only thing the
    > beach ball means is that an application is not taking events out of
    > its queue fast enough.

    Indeed.

    > From an application's perspective, the Unix select() function is
    > presumably called from the run loop and used to block the calling
    > thread unless at least one input source (included in the select()
    > call) has pending input.  The window server's event queue is just
    > one input source for select().  Timers,
    > distributed messages, apple events, distributed notifications, and
    > any file descriptors you add are
    > included in the select().

    AFAIK run loops are built on Mach messaging primitives, not UNIX
    select(), at least on Mac OS X.  select() certainly used to be used
    by X11 apps, though there are other mechanisms in modern UNIXen such
    as kqueue()/kevent().

    However, all of this (aside from NSThread's +setThreadPriority:) is
    heading off-topic.

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
previous month october 2007 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