Page 1 of 1

Design: Exception semantics

Posted: Fri Jul 25, 2003 6:03 am
by mystran
Userspace exceptions.. POSIX has signals, and other systems usually have some kind of exception mechanism.

Now, I'm designing exception mechanism for my kernel.
Since my IPC design basicly works in such a way that anything a process sees that is not just memory, is represented by a reference to object (threads, connections, memory mappings), I'm thinking of a system that would allow one to send exceptions to any object.

Exceptions sent to a thread are easily implemented by throwing the thread into an exception handler, but exceptions sent to other objects not directly bound to a specific thread are somewhat a question mark.

Unix signals work such that a signal sent to process causes one (arbitary) thread that hasn't blocked the signal to receive it. This is all fine, as long as one has a limited amount of different signals, but even then it's somewhat confusing.. (if all systems had exactly the same semantics, this would be a little less painful)

Now, what I want, is to have each exception represented by a (binary) name, and possibly an optional parameter.
I think it's acceptable to have one generic exception handler that identifies the actual exception and calls the actual handler, also taking care of register saving and restoring.

Now, my problems are what should happen when a thread receives an exception while in a RPC operation, and what would be a clean way to deal with async notifications.

Should I let the RPC operation to complete, and provide some other means of interrupting the thread? Should I only allow threads to receive exceptions from other threads in the same process, and queue exceptions sent to the process in some way, such that a special thread could then check them, one by one, and deliver the important ones to other threads? Does this sound reasonable?

Your ideas, suggestions, etc?
What kind of exception/signal/event mechanism do you have/plan?

added: my system is based on message-passing microkernel..

Re:Design: Exception semantics

Posted: Fri Jul 25, 2003 6:22 am
by Solar
Pfff... I'm not sure "Exception" is the right term to use here, "signaling" or even "message passing" sounds more appropriate. (I thought you were talking about either CPU or C++ exceptions, here...)

Re:Design: Exception semantics

Posted: Fri Jul 25, 2003 6:29 am
by mystran
Indeed, I was actually talking somewhat about both, since I'm planning on using the same mechanism for sending CPU exceptions and exceptions on remote objects, hopefully in such a way that an object-oriented language can be enabled to catch them as language exceptions...

To clarify myself, I want a generic method for delivering anything that a thread might not expect to receive, and I'm wondering what the method of delivering should be in order to make it reliable, safe, yet simple (not necessary on kernel interfacing library level/language runtime level, but on application level).

Re:Design: Exception semantics

Posted: Fri Jul 25, 2003 6:30 am
by Tim
mystran wrote: Userspace exceptions.. POSIX has signals, and other systems usually have some kind of exception mechanism.
I would prefer to separate the concepts of "exception" and "signal". Exceptions signify that something abnormal has happened, such as accessing protected memory; signals are a general way of something notifying a process and/or thread of something, such as a request to quit.
Unix signals work such that a signal sent to process causes one (arbitary) thread that hasn't blocked the signal to receive it. This is all fine, as long as one has a limited amount of different signals, but even then it's somewhat confusing.. (if all systems had exactly the same semantics, this would be a little less painful)
It also gets confusing with more than a few threads. If we separate exceptions and signals, then an exception gets given to the thread that raised it, and a signal gets handled some other way (maybe synchronously).
Now, my problems are what should happen when a thread receives an exception while in a RPC operation, and what would be a clean way to deal with async notifications.
An exception (in my sense) can't happen while a thread is blocked. A signal can, so what happens depends on how signals are given to a process. A signal handler could be one thread per process sitting in an ask_for_signal() loop, which solves all of this. If it needs to end a thread, you cancel pending RPC operations the in a general way (which is a separate issue).

Windows has a mechanism similar to Posix signals called user APCs (asynchronous procedure calls). An APC lets you direct another thread to call a function and return to where it left off. However, a user APC can only be triggered when the target thread is in a special alterable state; that is, sleeping or waiting with the Alertable flag set. An alertable sleep or wait call returns a special error code which tells the caller that an APC occurred.
Should I let the RPC operation to complete, and provide some other means of interrupting the thread?
Maybe. The RPC operation may take a long time to complete (imagine a signal sent to a process waiting for a key press).
Should I only allow threads to receive exceptions from other threads in the same process, and queue exceptions sent to the process in some way, such that a special thread could then check them, one by one, and deliver the important ones to other threads? Does this sound reasonable?
This sounds like my dedicated signal handler thread idea above.

Re:Design: Exception semantics

Posted: Fri Jul 25, 2003 6:52 am
by mystran
Tim, I think you are probably right. The asynchronous call could either fail when there's no thread waiting, or leave the signal in a mailbox. Could be controllable by the receiving process..

That would also solve the problem of processes sending each other signals, that look like CPU exceptions. In (at least some, including Linux) POSIX systems there's nothing that prevents you from sending SIGSEGV or SIGFPU to another process, as long as you just have permissions to send a signal in the first place (same user or root) which makes the whole concept even messier.

It seems that I was too concentrated to improving the UNIX solution, that I never really considered to really separate the two concepts..

Re:Design: Exception semantics

Posted: Fri Jul 25, 2003 7:18 am
by Tim
The Unix way is OK for one thread per process, but it gets messy when more than one thread is used. The way I outlined separates "asking a process to do something" (signals) and "telling a thread something has happened" (exceptions).

Re:Design: Exception semantics

Posted: Fri Jul 25, 2003 7:33 am
by Solar
Also note that language exceptions can't always be passed to an object to handle them. main() isn't an object (at least in C++), but it can catch() exceptions... I am not sure if the concepts of signals, hard exceptions and language exceptions are that compatible after all.

Not sure though, I might be totally wrong, your mileage may vary, take with a grain of salt etc. etc. pp.

:-)

Re:Design: Exception semantics

Posted: Fri Jul 25, 2003 11:08 am
by Pype.Clicker
imho, you should not mix exceptions and signals (or whatever you call them) at the conceptual level, even if it intrisically share some implementation techniques.

If you look a bit deeper at what's happening, the signal mechanism acts as an interrupt handler on a virtual processor: when the signal is received, the current operation is interrupted and the signal is handled. When the signal handler completes, it will simply return to the interrupted operation, which should not notice any change.
This behaviour can safely be used to support GUI events, I/O completion notifications, etc.

In the case of an exception, the current operation is cancelled, which means we have to restore a previous state (basically by unrolling the stack and calling any sort of destructors)...

A very simple way to handle this using signals would look like:

Code: Select all

{ 
    thread_local sigcontext resumepoint;
    switch (sigsetjmp(resumepoint)) {
       case 0: do_system_call(); break;
       case 1: throw new ExceptionStuff1();
       case 2: throw new ExceptionStuff2();
       case 3: throw new ExceptionStuff3();
   }
}

Error1_signal_handler() {
    siglngJmp(resumepoint, 1);
}
As the OS isn't suppose to know what language is used by the application, i would say that it can hardly call the 'good' exception. This is rather the problem of the runtime library to translate OS faults signals like "BrokenPipe" or "EndOfFile" into the appropriate exception...