[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
QUIT
I'm sorry, but I just will not support the idea of a single function QUIT
as is currently being discussed. If the problem were re-cast, it might be
soluble, but I believe the problem as I've seen it stated thus far is just
plain insoluble.
I base my criticisms on experience that I have from create a portable
QUIT function for use in Macsyma internals. I created such a function
using various non-portable primitives provided by particular dialects
I was studying. As with the GC problem, I found that the idea seemed
superficially plausible but just didn't work out in practice. Here are
some of my observations and conclusions ...
1. Where is control transfered?
Of the implementations which primitively offer some variant of QUIT,
all that I know of are on partitioned address space machines which
have a basically tree-structured process system that offers a
distinguished superior (usually an exec) to which it is obvious that
control should be transfered upon call to QUIT.
Shared address space machines (ie, Lisp Machines) have the problem
that there is no tree of processes. All occupy an equal status and
there is no obvious process to which control should be returned.
2. What is a process?
On partitioned address space machines, each process typically
comes with its own "global" state. Killing a process means killing its
"global" state. On shared address machines, killing the process will
generally kill only its dynamic state, not its global state (which
is generally intertwined with the global state of other processes).
To kill its global state means killing the global state of sibling
activities, which may be highly undesirable.
3. Can the process be resumed?
Even among partitioned address space machines, there is disagreement
about whether exiting (to the exec) means that you can re-enter later.
4. What does it mean for a process to be resumed?
Presumably resuming leaves the global state intact. Does it restart
the process or does the call to QUIT just return NIL?
5. If a process is killed permanently, are the associated UNWIND-PROTECT
cleanup forms guaranteed to run first?
Obviously, some of these issues cannot be answered by the Common-Lisp
committee. They are architectural issues beyond the scope of the
language. If we standardize on any meaning for QUIT, however, it must be
guided by an understanding that people do not use linguistic primitives
in the absence of intent, and that we should not provide primitives
which do not allow the programmer to clearly specify some meaningful
intent. In light of the questions I've raised above, I hope it's clear
that definitions like "Exits the Lisp system" do not make any intent
clear.
Here are some real-life scenarios that I see...
1. If the intent was to exit, what if there was no place to go?
On the 3600, the Lisp Listener doubles as an exec. It is the
standard place to which programmers return to give commands,
not a place to be returned from. Having a "user interface"
function named QUIT which was a no-op when typed to Lisp would
be very confusing. Having it randomly select another activity
would be fairly useless. I feel that people don't interactively
ask to exit something unless they think there is an obvious
place to go.
2. If the intent is to exit temporarily and the exit turns out to
be permanent, this can have remarkably drastic consequences. A
user of Macsyma would be phenomenally irritated if I offered a
temporary-exit function and it ended up exiting permanently
before s/he had a chance to save the MACSYMA's state.
3. If the intent was to exit permanently and the program was
allowed to proceed, the effects of continuing could be very
strange. I've found myself resorting to things like:
(PROGN (QUIT) ;Try a permanent exit
(...)) ;If we got here, the QUIT didn't work,
;so try cleaning up enough to continue
or even:
(LOOP (QUIT)) ;Insist on a permanent exit!
4. If the intent was to exit "lisp" permanently, destroying global
state, I'd argue that it could not possibly have been the intent
of any portable program to really kill everything on the machine
since those other things are beyond the scope of Common Lisp and
not something that CL programs have any obvious way to reason
about.
On the 3600, you can't opt to "start over" without taking the
Editor, Mail Reader, Peek, Telnet Windows, etc. with it. Some
people here at Symbolics do all their work from the same Lisp for
several weeks at a time, building up lots of state which they
don't want thrown away casually. There is no "starting over" that
is not synonymous with "cold booting". In the case of server
machines, this would mean that file connections would be broken,
mail would stop being delivered until the (sometimes long) cold
boot sequence had run, etc. In fact, the boot sequence may not
begin automatically just because I halt my machine. If I was
dialing in from home, I might have to go to work to initialize
the system again.
Some non-Lispms have an in-Lisp editor even though they have
other processes which are separable. Perhaps some of those
users use that editor only for editing Lisp and are content to
have the editor and the lisp go away as a unit because they do
other text editing in an editor that doesn't go away with Lisp,
but that's presumably a property of the user rather than the
system.
The real problem here is that there is no such thing as exiting in the
pure abstract. Exiting means to pass through an abstract boundary
between an abitrarily chosen inside and outside. In the CL spec, we have
remained intentionally silent on the issue of where that line is drawn
in order to accomodate both Lispm-based and conventional systems. I
think that corollary to this silence is the fact that functions which
attempt to cross the boundary are ill-defined. Not only do some systems
draw the boundary in different places than others, but some
intentionally don't draw it at all.
I don't care whether the primitive is called QUIT, EXIT, EXIT-TO-SYSTEM,
or whatever. The names themselves are not the problem. I only care that
any names we choose have a very clear behavior and that I can reason
about at coding time, or that my programs can reason about at runtime
prior to actually invoking the primitive which actually attempts to exit.
I don't plan to seriously consider any proposal for a QUIT primitive
which does not carefully address these issues.
- References:
- Re: exit-to-system
- From: Bernard S. Greenberg <BSG@STONY-BROOK.SCRC.Symbolics.COM>
- Re: exit-to-system
- From: Masayuki Ida <a37078%ccut.u-tokyo.junet%utokyo-relay.csnet@CSNET-RELAY.ARPA>