
The current behaviour of System.exitWith doesn't really make sense in a concurrent environment. The current semantics is to: - halt the current thread - run all finalizers (concurrently with any other currently running threads) - stop the system as soon as all finalizers have finished. One high-priority problem we also have is that a program which calls System.exitWith from inside GHCi will shut down the whole system. Here's my current proposal: - introduce a new exception constructor: ExitException ExitCode - System.exitWith causes (ExitException code) to be raised in the current thread. - If this exception propogates to the top of the thread, then the main thread is also sent (ExitException code). This only happens for a standalone executable (ie. one which was started by PrelMain.mainIO). - If this exception propogates to the top of the main thread, then the system is shut down as before - all finalizers are run to completion, then we exit. For GHCi, we can obviously catch the ExitException exception and recover, and there is no main thread in this case. An alternative is just to omit the third point and let the programmer handle propagation of the ExitException to the main thread. This is somewhat consistent with our current policy of leaving these kind of decisions up to the programmer: 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. Cheers, Simon

In reply to Simon Marlow,
- introduce a new exception constructor: ExitException ExitCode
- System.exitWith causes (ExitException code) to be raised in the current thread.
Not entirely relevant, in fact, barely at all but what are the odds of user extensible Exceptions (like ML) coming into GHC and having a proper hierarchy of exceptions integrated in the libraries?

Tue, 22 May 2001 15:43:45 +0100, Simon Marlow
- If this exception propogates to the top of the thread, then the main thread is also sent (ExitException code). This only happens for a standalone executable (ie. one which was started by PrelMain.mainIO).
This looks like a strange exception for me (i.e. the fact that it propagates to the main thread). And it's weird to have it as an asynchronous exception in the main thread. I would drop this rule and let 'exitWith ExitSuccess' be the way to commit suicide by a thread, as if it completed, which degenerates to the Haskell 98 interpretation in a single-threaded program. BTW, I don't quite like the fact that 'exitFailure' looks simpler than 'exitWith ExitSuccess'. -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK

"Simon Marlow"
The current behaviour of System.exitWith doesn't really make sense in a concurrent environment. The current semantics is to:
- halt the current thread
- run all finalizers (concurrently with any other currently running threads)
- stop the system as soon as all finalizers have finished.
One high-priority problem we also have is that a program which calls System.exitWith from inside GHCi will shut down the whole system.
Here's my current proposal:
- introduce a new exception constructor: ExitException ExitCode
- System.exitWith causes (ExitException code) to be raised in the current thread.
- If this exception propogates to the top of the thread, then the main thread is also sent (ExitException code). This only happens for a standalone executable (ie. one which was started by PrelMain.mainIO).
- If this exception propogates to the top of the main thread, then the system is shut down as before - all finalizers are run to completion, then we exit.
For GHCi, we can obviously catch the ExitException exception and recover, and there is no main thread in this case.
An alternative is just to omit the third point and let the programmer handle propagation of the ExitException to the main thread. This is somewhat consistent with our current policy of leaving these kind of decisions up to the programmer: 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.
I think, having the third point is good, because the Haskell report requires that Computation exitWith code terminates the program, returning code to the program's caller. Cheers, Manuel

Wed, 23 May 2001 16:50:42 +1000, Manuel M. T. Chakravarty
I think, having the third point is good, because the Haskell report requires that
Computation exitWith code terminates the program, returning code to the program's caller.
Well, it says also that Actions, however, must be ordered in a well-defined manner for program execution -- and I/O in particular -- to be meaningful. Haskell 's I/O monad provides the user with a way to specify the sequential chaining of actions, and an implementation is obliged to preserve this order. which is not true in a threaded program. -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK

"Simon Marlow"
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 else). 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): http://www.cs.utah.edu/flux/papers/redline-hotos7-base.html http://www.cs.utah.edu/flux/papers/kaffeos-osdi00-base.html Matthew Flatt (http://www.cs.utah.edu/~mflatt/) has encountered similar issues in MrEd/DrScheme/MzScheme (which is more or less GHCi for Scheme): http://www.cs.rice.edu/CS/PLT/Publications/icfp99-ffkf.pdf Godmar emphasises the OS side of things whereas Matthew comes at the same issues from a language point of view. -- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/
participants (5)
-
Alastair David Reid
-
Manuel M. T. Chakravarty
-
Marcin 'Qrczak' Kowalczyk
-
Simon Marlow
-
Smelly Pooh