[Gc] Problems with exceptions in OSX

Juan Jose Garcia-Ripoll juanjose.garciaripoll at googlemail.com
Mon May 25 01:27:14 PDT 2009


I am writing to the list because I use the garbage collector (v7.1) in
an implementation of Common Lisp (ecls.sf.net). I currently have a
problem with the Darwin port. The situation is as follows.

ECL uses mprotect on regions of memory that have not been allocated by
the gc. This is a trick to get a quick dispatch of deferred C signals
and we need it -- otherwise performance is simply too bad. The problem
is that under Darwin, the gc intercepts the SIGBUS exception,
recognizes that it is not due to the gc and is not able to forward it.
The reason is that the logic of the forwarding function is bougs: it
inspects this exception, finds out that it has a handler and then it
refuses to forward.

A proper implementation should be, IMHO, as follows (os_dep.c) Note
that the code before and after the switch statement had also to be
changed: if the exception is not related to thread states then
thread_get_state will fail miserably.

static kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task,
					  exception_type_t exception,
					  exception_data_t data,
					  mach_msg_type_number_t data_count)
  unsigned int i;
  kern_return_t r;
  mach_port_t port;
  exception_behavior_t behavior;
  thread_state_flavor_t flavor;

  thread_state_t thread_state = NULL;
  mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;

  for(i=0; i < GC_old_exc_ports.count; i++)
    if(GC_old_exc_ports.masks[i] & (1 << exception))
    ABORT("No handler for exception!");

  port = GC_old_exc_ports.ports[i];
  behavior = GC_old_exc_ports.behaviors[i];
  flavor = GC_old_exc_ports.flavors[i];

  if (behavior == EXCEPTION_STATE || behavior == EXCEPTION_STATE_IDENTITY) {
    r = thread_get_state(thread, flavor, thread_state, &thread_state_count);
    if(r != KERN_SUCCESS)
      ABORT("thread_get_state failed in forward_exception");

  switch(behavior) {
      r = exception_raise_state(port, thread, task, exception, data, data_count,
				&flavor, thread_state, thread_state_count,
				thread_state, &thread_state_count);
      r = exception_raise_state_identity(port, thread, task, exception, data,
					 data_count, &flavor, thread_state,
					 thread_state_count, thread_state,
    case EXCEPTION_DEFAULT: /* default signal handlers */
    default: /* user supplied signal handlers */
      r = exception_raise(port, thread, task, exception, data, data_count);

  if (behavior == EXCEPTION_STATE || behavior == EXCEPTION_STATE_IDENTITY) {
    r = thread_set_state(thread, flavor, thread_state, thread_state_count);
    if(r != KERN_SUCCESS)
      ABORT("thread_set_state failed in forward_exception");

  return r;

Instituto de Física Fundamental, CSIC
c/ Serrano, 113b, Madrid 28009 (Spain)

More information about the Gc mailing list