Para que el monitor pueda manejar las excepciones debe tener asociado un puerto de excepcion al hilo V86, y atender los mensajes que lleguen por este puerto, y después mandar a llamar al manejador de excepciones. Esto se realiza con el llamado exc_server e implantando el protocolo catch_exception_raise.
Una vez que el monitor ha creado el proceso V86 se queda en un ciclo esperando recibir algún mensaje de error por el puerto de excepción que asoció al hilo V86:
port_t port_ex; struct msg { msg_header_t header; char data[64]; } i_msg, o_msg, *i, *o; while(1) { i = &i_msg; o = &o_msg; i_msg.header.msg_size = 64; i_msg.header.msg_local_port = port_ex; if((msg_receive( &(i_msg.header), MACH_RCV_MSG, 0)) r==RCV_SUCCESS) { if (exc_server(&(i_msg.header), &(o_msg.header))) msg_send( &(o_msg.header), MACH_SEND_MSG, 0); } }Con el llamado msg_receive el monitor espera un mensaje a través del puerto port_ex --el mensaje de entrada i_msg tiene asociado el puerto de excepción--. Una vez que recibe el mensaje, manda a ejecutar al manejador de excepciones del usuario (la implantación de catch_exception_raise). Y, finalmente, el ciclo se termina cuando le envía un mensaje al kernel, para informar que ha manejado la excepción.
El usuario tiene la opción de escribir su manejador de excepciones implantando el protocolo catch_exception_raise.
kern_return_t catch_exception_raise(port_t p, thread_t th, task_t tk, int exception, int code, int subcode) { i386_thread_state_t state; kern_return_t error; thread_get_state(th, i386_THREAD_STATE, &state, &state_count); switch(exception) { case EXC_BAD_INSTRUCTION: do_bad_instruction (&state); break; case EXC_BREAKPOINT: do_breakpoint (&state); break; case EXC_BAD_ACCESS: do_bad_access(&state, subcode); break; case EXC_ARITHMETIC: do_arithmetic (&state, code, subcode); break; }Entonces el monitor puede ejecutar una función para cada tipo de excepción que se atrape.
El manejo de excepciones requiere que el proceso monitor realice operaciones de lectura y escritura a la tarea V86, esto se debe a que en la simulación de una instrucción es necesario conocer cual instrucción especial está generando la excepción --Mach notifica al monitor que ha ocurrido una excepción de protección, mas no le indica que instrucción lo ha ocasionado--, y dependiendo de esta instrucción, se procede a modificar el espacio de direcciones de la tarea V86 y el estado del hilo V86, tal y como lo haría el procesador si ejecutara la instrucción especial.
Para realizar estas operaciones se distinguen dos módulos principales en la aplicación: el proceso V86 y el monitor.