Discussion:
enhancing Force Quit or improving user-driven diagnostics
John Hawkinson
2012-01-15 16:18:18 UTC
Permalink
I've had a number of cases recently where I would like to encourage
some of my site's users to SIGABRT processes when they hang (so I can
at least have a crash report to take to a software vendor or stare at
myself, and maybe even a core dumps), but some of my users really
really like to Force Quit when things go wrong (and they're in a hurry).

While trying to modify user behavior is hard, I'd like to give them the
option to send SIGABRT and make it as easy as possible.

Is it possible to trap the Cmd-Opt-Escape sequence and redirect it to
a custom implementation?

Is there any prior art in this space?


I understand that it currently goes to loginwindow, and I assume there
is no hope in modifying loginwindow to add one more
button. [Hmm. Maybe I could modify loginwindow to send SIGABRT instead
of SIGKILL though? That might be unwise. ]

I know I can disable force quit entirely with the Kiosk API and
kUIOptionDisableForceQuit. But that's not very palatable.
(Though I suppose if I could disable it and then bind another key to
invoke my custom app, that would not be so bad).

Is it practical to use a Quartz Event Tap for this purpose?

Thoughts appreciated.

(It's not for "my app" so I suppose this is a sysadmin-ish kind of
question, but I'm certainly prepared to write code to accomplish it.)


TANGENT:
Another thing I would like to do is to take a screenshot of app state
at the time a crash happens. Does anyone have any experience extending
ReportCrash to do something like that?

Perhaps it is as easy as a shell-script wrapper.

It is amusing to me that my ability to take screenshots of app state
at crash time improves exponentially when core dumps are enabled.
When you have tends of seconds to realize the app is crashing, taking
a screenshot is pretty easy. And they can be invaluable in debugging
complex problems.


Thanks, all.

--***@mit.edu
John Hawkinson

p.s.: If you think this is off-topic for this list, I'd appreciate a
redirection.
Kevin Reid
2012-01-15 17:51:20 UTC
Permalink
Post by John Hawkinson
I've had a number of cases recently where I would like to encourage
some of my site's users to SIGABRT processes when they hang (so I can
at least have a crash report to take to a software vendor or stare at
myself, and maybe even a core dumps), but some of my users really
really like to Force Quit when things go wrong (and they're in a hurry).
While trying to modify user behavior is hard, I'd like to give them the
option to send SIGABRT and make it as easy as possible.
Is it possible to trap the Cmd-Opt-Escape sequence and redirect it to
a custom implementation?
How about setting a signal handler for SIGTERM, the signal Force Quit sends?
--
Kevin Reid <http://switchb.org/kpreid/>
John Hawkinson
2012-01-15 18:38:22 UTC
Permalink
Post by Kevin Reid
How about setting a signal handler for SIGTERM, the signal Force Quit sends?
It's not my app, so it's difficult to install signal handlers.


I guess Force Quit sends a SIGTERM before it sends SIGKILL.

I am not convinced that the app's signal handling is in
good order, and the signal handler would cause some confusion in the
stack trace. I would prefer to leave the faulting program's
execution environment unaltered by my diagnostics.

(Certainly a solution that works for all apps is more along the lines
of what I am looking for than a solution that works for just one. But
I suppose an LD_PRELOAD -- err, I mean DYLD_INSERT_LIBRARIES -- of a
signal handler is a possibility if the more general solution doesn't
pan out).

THanks.

--***@mit.edu
John Hawkinson
John Hawkinson
2012-01-16 21:56:53 UTC
Permalink
Thanks for the inspiration, Kevin.
Post by John Hawkinson
(Certainly a solution that works for all apps is more along the lines
of what I am looking for than a solution that works for just one. But
I suppose an LD_PRELOAD -- err, I mean DYLD_INSERT_LIBRARIES -- of a
signal handler is a possibility if the more general solution doesn't
pan out).
Actually, an easier answer is to interpose loginwindow's call to kill(),
because it doesn't seem to call kill() very often.
As a first cut, the attached seems to work. Tested under 10.6.8.

I vaguely wonder how hard it would be to add a button next to Force
Quit (easy: just edit the nib), wired up the same way, and then have
the interposition handler determine which button was pressed (I really
have no idea on that one).

In this implementation, loginwindow sends SIGTERM which gets converted
to SIGABRT, and then since writing core dumps takes awhile, it sends
a SIGKILL as well. But that's OK, because once the kernel has started
writing the core dump, SIGKILL does no harm.

--***@mit.edu
John Hawkinson
Kyle Sluder
2012-01-17 16:19:29 UTC
Permalink
I'm going to suggest a different tack.

man SubmitDiagInfo(1) describes how Apple takes care of crash reports:
ReportCrash(1) is automatically invoked by launchd when it detects a
program has crashed. That generates a crash report in the user's
~/Library/Logs/DiagnosticReports directory (or
/Library/Logs/DiagnosticReports for root). SubmitDiagInfo comes along
and periodically submits that info to Apple and cleans out logs that
are older than a month.

So why not create a system-wide per-user launchd agent that behaves
like SubmitDiagInfo? Have a periodic launchd task that enumerates the
contents of ~/Library/Logs/DiagnosticReports and sends you any
information you want.

No interposition required, and Apple has set a good precedent for this
technique.

--Kyle Sluder
Post by John Hawkinson
Thanks for the inspiration, Kevin.
Post by John Hawkinson
(Certainly a solution that works for all apps is more along the lines
of what I am looking for than a solution that works for just one. But
I suppose an LD_PRELOAD -- err, I mean DYLD_INSERT_LIBRARIES -- of a
signal handler is a possibility if the more general solution doesn't
pan out).
Actually, an easier answer is to interpose loginwindow's call to kill(),
because it doesn't seem to call kill() very often.
As a first cut, the attached seems to work. Tested under 10.6.8.
I vaguely wonder how hard it would be to add a button next to Force
Quit (easy: just edit the nib), wired up the same way, and then have
the interposition handler determine which button was pressed (I really
have no idea on that one).
In this implementation, loginwindow sends SIGTERM which gets converted
to SIGABRT, and then since writing core dumps takes awhile, it sends
a SIGKILL as well. But that's OK, because once the kernel has started
writing the core dump, SIGKILL does no harm.
 John Hawkinson
John Hawkinson
2012-01-17 16:32:14 UTC
Permalink
Post by Kyle Sluder
ReportCrash(1) is automatically invoked by launchd when it detects a
program has crashed. That generates a crash report in the user's
I think you've misunderstood. Force Quit doesn't invoke SubmitDiagInfo
or ReportCrash, so no crash report is collected. It just terminates
the process without diagnostics.

Asking my users to fire up Activity Monitor and use View > Send Signal
(SIGABRT), or to use kill -ABRT from the shell appears have
empirically determined to be losing strategies. It is like they have
Cmd-Opt-Esc *click* hardwired into their brains at high-priority :)

--***@mit.edu
John Hawkinson
Kyle Sluder
2012-01-17 16:36:52 UTC
Permalink
Post by John Hawkinson
Post by Kyle Sluder
ReportCrash(1) is automatically invoked by launchd when it detects a
program has crashed. That generates a crash report in the user's
I think you've misunderstood. Force Quit doesn't invoke SubmitDiagInfo
or ReportCrash, so no crash report is collected. It just terminates
the process without diagnostics.
Huh. For some reason I thought it always put up the "You have forced
this app to quit" dialog. But I guess it only does that if the app is
unresponsive.

Carry on, then! :)

--Kyle Sluder

Loading...