Poll: System.exitWith behaviour

Alastair David Reid [email protected]
30 May 2001 14:29:32 -0600

"Simon Marlow" <[email protected]> writes:
> One high-priority problem we also have is that a program which calls
> System.exitWith from inside GHCi will shut down the whole system.
> [...]
> we currently don't implement any kind of process hierarchy, and
> there is no requirement for child threads to complete before the
> program exits, for example.

The approach we've taken here in Utah (in the context of Java
operating systems) is to apply the following (standard) distinction
between threads and processes:

o Threads provide multiple concurrent streams of execution (and nothing

  Threads are not strongly isolated from each other so killing
  a thread can fatally wound another thread, redirecting stdout
  will affect other threads, etc.

o Processes are sets of threads which are isolated from each other.

  In particular, you can kill one process without affecting the
  integrity of other processes and you can redirect stdout in one
  process independently of other processes.  

  Processes are usually implemented using memory protection and often
  implies separate address spaces in OSs like Unix and Windows but, in
  the OS research community, that is viewed as an implementation
  technique rather than being part of the definition.  (For example,
  there are a number of single address space operating systems (SASOS)
  and early JavaOSs tried to use strong typechecking in place of 
  memory protection.)

  [Isolation may mean different things in different systems.  For
  example, you might want to enforce some resource limits to protect
  processes against memory, cpu or bandwidth hogs.]

Translating this into the GHCi situation, it seems that you want to
treat GHCi and the user's program as two separate processes and we can
imagine that anyone else writing an interpreter in Haskell would want
to do so too.  (e.g., it might be a useful way of structuring my
graphics library too).

When you come to implement this model, another useful concept from
operating systems is the notion of a "red line".  This is the border
between "untrusted" user code and "trusted" system code.  In a
conventional OS, this line is the user-kernel boundary and is
implemented using system calls, hardware traps, file descriptor
tables, etc. but the concept is useful even if it is implemented using
a combination of type safety, careful programming and exception
handlers.  In the current system, most of the IO library should lie
beneath the red line.  If a notion of process were added, then some
parts of process creation/killing, running of finalizers, locking,
etc.  would lie beneath the red line.  The value of this concept is:

1) Having a word for it.

2) As long as you have a clear statement of what level of "isolation"
   you want to achieve, you have a clear definition of what you have
   to protect against when you cross the red line.  This is useful for
   answering questions like: Is it enough to add an exception handler?
   Should you add a timeout mechanism too?  What resources have to be
   revocable?  What resources need an extra layer of indirection so
   that you can implement different namespaces (e.g., file descriptors
   in Unix allow different processes to define stdout differently)

Godmar Back (http://www.cs.utah.edu/~gback/) has explored this in
detail (it will form part of his forthcoming PhD thesis):


Matthew Flatt (http://www.cs.utah.edu/~mflatt/) has encountered
similar issues in MrEd/DrScheme/MzScheme (which is more or less GHCi
for Scheme):


Godmar emphasises the OS side of things whereas Matthew comes at the
same issues from a language point of view.

Alastair Reid        [email protected]        http://www.cs.utah.edu/~reid/