Пример #1
0
/* this is the thread which forwards of exceptions read from the exception
   server off to our exception catchers and then back out to the other
   thread */
void exception_thread(void *shared_thread_state)
{
  mach_msg_header_t *message;
  mach_msg_header_t *reply;
  kern_return_t retval;

#ifdef USE_THREAD_LOCAL
  pthread_setspecific(scheme_thread_local_key, shared_thread_state);
#endif

  /* allocate the space for the message and reply */
  message = (mach_msg_header_t*)malloc(sizeof(mach_exc_msg_t));
  reply = (mach_msg_header_t*)malloc(sizeof(mach_reply_msg_t));
  /* do this loop forever */
  while(1) {
    /* block until we get an exception message */
    retval = mach_msg(message, MACH_RCV_MSG, 0, sizeof(mach_exc_msg_t), 
		      exc_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
    /* forward off the handling of this message */
    if(!exc_server(message, reply)) {
      GCPRINT(GCOUTF, "INTERNAL ERROR: exc_server() didn't like something\n");
      abort();
    }
    /* send the message back out to the thread */
    retval = mach_msg(reply, MACH_SEND_MSG, sizeof(mach_reply_msg_t), 0, 
		      MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
  }
}
Пример #2
0
/*
 * This message server catches server exceptions. It runs in a dedicated thread.
 */
void *
server_exception_catcher(
	void	*arg)
{
	struct server_thread_priv_data	priv_data;
	kern_return_t			kr;
#define MSG_BUFFER_SIZE	8192
	union request_msg {
		mach_msg_header_t	hdr;
		mig_reply_error_t	death_pill;
		char			space[MSG_BUFFER_SIZE];
	} *msg_buffer_1, *msg_buffer_2;
	mach_msg_header_t		*request;
	mig_reply_error_t		*reply;

	cthread_set_name(cthread_self(), "server exc catcher");
	server_thread_set_priv_data(cthread_self(), &priv_data);

	kr = vm_allocate(mach_task_self(),
			 (vm_address_t *) &msg_buffer_1,
			 2 * sizeof *msg_buffer_1,
			 TRUE);
	if (kr != KERN_SUCCESS) {
		MACH3_DEBUG(0, kr, ("server_exception_catcher: vm_allocate"));
		panic("server_exception_catcher");
	}

	msg_buffer_2 = msg_buffer_1 + 1;
	request = &msg_buffer_1->hdr;
	reply = &msg_buffer_2->death_pill;

	do {
		kr = mach_msg(request, MACH_RCV_MSG,
			      0, sizeof *msg_buffer_1,
			      server_exception_port,
			      MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
		if (kr != MACH_MSG_SUCCESS) {
			MACH3_DEBUG(1, kr,
				    ("server_exception_catcher: mach_msg"));
			panic("server_exception_catcher: receive");
		}

		if (exc_server(request, &reply->Head)) {}
		else {
			printk("server_exception_catcher: invalid message"
			       "(id = %d = 0x%x)\n",
			       request->msgh_id, request->msgh_id);
		}
		panic("server_exception_catcher: what now ?");
	} while (1);
       
	cthread_detach(cthread_self());
	cthread_exit((void *) 0);
	/*NOTREACHED*/
	return (void *) 0;
}
Пример #3
0
static any_t exc_thread(ports_t *port_p)
{
    kern_return_t r;
    char *msg_data[2][64];
    msg_header_t *imsg = (msg_header_t *)msg_data[0],
    *omsg = (msg_header_t *)msg_data[1];
    
    /* Wait for exceptions */
    while(1) {
	imsg->msg_size = 64;
	imsg->msg_local_port = port_p->exc_port;
	r = msg_receive(imsg, MSG_OPTION_NONE, 0);
	if (r == RCV_SUCCESS) {
	    /* Give the message to the Mach exception server. */
	    if (exc_server(imsg,omsg)) {
		/* send the reply message that exc_serv gave us. */
		r = msg_send(omsg, MSG_OPTION_NONE, 0);
		if (r != SEND_SUCCESS) {
		    mach_error("exc_thread msg_send",r);
		    exit(1);
		}
	    }
	    else {
		/* exc_server refused to handle the imsg. */
		exit(2);
	    }
	}
	else {
	    /* msg_receive returned an error. */
	    mach_error("exc_thread msg_receive",r);
	    exit(3);
	}
	
	/* Pass the message to the old exception handler, if necessary. */
	if (pass_on == TRUE) {
	    imsg->msg_remote_port = port_p->old_exc_port;
	    imsg->msg_local_port = port_p->clear_port;
	    r = msg_send(imsg, MSG_OPTION_NONE, 0);
	    if (r != SEND_SUCCESS) {
		mach_error("msg_send to old_exc_port",r);
		exit(4);
	    }
	}
    }
}
Пример #4
0
/*   FUNCTIONS */
static void *exc_thread(void *junk) {
    mach_msg_return_t r;
    /* 
       These two structures contain some private kernel data. We don't need to
       access any of it so we don't bother defining a proper struct. The
       correct definitions are in the xnu source code. 
    */
    struct {
        mach_msg_header_t head;
        char data[256];
    } reply;
    struct {
        mach_msg_header_t head;
        mach_msg_body_t msgh_body;
        char data[1024];
    } msg;
    
    for(;;) {
        r = mach_msg(
            &msg.head,
            MACH_RCV_MSG|MACH_RCV_LARGE,
            0,
            sizeof(msg),
            exception_port,
            MACH_MSG_TIMEOUT_NONE,
            MACH_PORT_NULL);
        if(r != MACH_MSG_SUCCESS) DIE("mach_msg");
        
        /* Handle the message (calls catch_exception_raise) */
        if(!exc_server(&msg.head,&reply.head)) DIE("exc_server");
        
        /* Send the reply */
        r = mach_msg(
            &reply.head,
            MACH_SEND_MSG,
            reply.head.msgh_size,
            0,
            MACH_PORT_NULL,
            MACH_MSG_TIMEOUT_NONE,
            MACH_PORT_NULL);
        if(r != MACH_MSG_SUCCESS) DIE("mach_msg");
    }
    /* not reached */
}
Пример #5
0
/*
 * Exception thread handler.
 */
static
void *
mach_exception_thread (void *arg)
{
	for (;;) {
		mach_exception_msg_t request;
		mach_exception_msg_t reply;
		mach_msg_return_t result;

		/* receive from "mach_exception_port" */
		result = mach_msg (&request.msg.header,
				   MACH_RCV_MSG | MACH_RCV_LARGE,
				   0,
				   sizeof (request),
				   mach_exception_port,
				   MACH_MSG_TIMEOUT_NONE,
				   MACH_PORT_NULL);

		g_assert (result == MACH_MSG_SUCCESS);

		/* dispatch to catch_exception_raise () */
		exc_server (&request.msg.header, &reply.msg.header);

		/* send back to sender */
		result = mach_msg (&reply.msg.header,
				   MACH_SEND_MSG,
				   reply.msg.header.msgh_size,
				   0,
				   MACH_PORT_NULL,
				   MACH_MSG_TIMEOUT_NONE,
				   MACH_PORT_NULL);

		/*
		If we try to abort the thread while delivering an exception. The port will be gone since the kernel
		setup a send once port to deliver the resume message and thread_abort will consume it.
		*/
		g_assert (result == MACH_MSG_SUCCESS || result == MACH_SEND_INVALID_DEST);
	}
	return NULL;
}
Пример #6
0
/* The main function of the thread listening for exceptions.  */
static void* mach_exception_thread(void* arg) {
  for (;;) {
    /* These two structures contain some private kernel data. We don't need
       to access any of it so we don't bother defining a proper struct. The
       correct definitions are in the xnu source code. */
    /* Buffer for a message to be received. */
    struct {
      mach_msg_header_t head;
      mach_msg_body_t msgh_body;
      char data[1024];
    } msg;
    /* Buffer for a reply message. */
    struct {
      mach_msg_header_t head;
      char data[1024];
    } reply;

    mach_msg_return_t retval;

    /* Wait for a message on the exception port. */
    retval =
        mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(msg),
                 our_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
    if (retval != MACH_MSG_SUCCESS) {
      abort();
    }

    /* Handle the message: Call exc_server, which will call
       catch_exception_raise and produce a reply message. */
    exc_server(&msg.head, &reply.head);

    /* Send the reply. */
    if (mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,
                 MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL) !=
        MACH_MSG_SUCCESS) {
      abort();
    }
  }
  return NULL;  // quiet warning
}
Пример #7
0
/*
 * Exception thread handler.
 */
static
void *
mach_exception_thread (void *arg)
{
	for (;;) {
		mach_exception_msg_t request;
		mach_exception_msg_t reply;
		mach_msg_return_t result;

		/* receive from "mach_exception_port" */
		result = mach_msg (&request.msg.header,
				   MACH_RCV_MSG | MACH_RCV_LARGE,
				   0,
				   sizeof (request),
				   mach_exception_port,
				   MACH_MSG_TIMEOUT_NONE,
				   MACH_PORT_NULL);

		g_assert (result == MACH_MSG_SUCCESS);

		/* dispatch to catch_exception_raise () */
		exc_server (&request.msg.header, &reply.msg.header);

		/* send back to sender */
		result = mach_msg (&reply.msg.header,
				   MACH_SEND_MSG,
				   reply.msg.header.msgh_size,
				   0,
				   MACH_PORT_NULL,
				   MACH_MSG_TIMEOUT_NONE,
				   MACH_PORT_NULL);

		g_assert (result == MACH_MSG_SUCCESS);
	}
	return NULL;
}
void *ExceptionHandlerThread(void *thread_arg) {
  mach_port_t handler_port = (mach_port_t) (uintptr_t) thread_arg;

  while (1) {
    struct {
      mach_msg_header_t header;
      uint8_t data[256];
    } receive;
    mach_msg_header_t reply;
    kern_return_t rc;

    receive.header.msgh_local_port = handler_port;
    receive.header.msgh_size = sizeof(receive);
    rc = mach_msg(&receive.header,
                  MACH_RCV_MSG | MACH_RCV_LARGE, 0,
                  receive.header.msgh_size, handler_port,
                  MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
    CHECK(rc == KERN_SUCCESS);
    CHECK(exc_server(&receive.header, &reply));
    exit(1);
  }

  return NULL;
}
Пример #9
0
static void *mach_exception_thread(void *data) {
  while (true) {
    struct {
      mach_msg_header_t head;
      mach_msg_body_t msgh_body;
      char data[1024];
    } msg;
    struct {
      mach_msg_header_t head;
      char data[1024];
    } reply;

    // wait for a message on the exception port
    mach_msg_return_t ret =
        mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(msg),
                 s_listen_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
    if (ret != MACH_MSG_SUCCESS) {
      LOG_INFO("mach_msg receive failed with %d %s", ret,
               mach_error_string(ret));
      break;
    }

    // call exc_server, which will call back into catch_exception_raise
    exc_server(&msg.head, &reply.head);

    // send the reply
    ret = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,
                   MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
    if (ret != MACH_MSG_SUCCESS) {
      LOG_INFO("mach_msg send failed with %d %s", ret, mach_error_string(ret));
      break;
    }
  }

  return NULL;
}
Пример #10
0
/*
 * This message server catches user task exceptions. Most user exceptions
 * will be received on the thread exception port. This server servers
 * only exceptions from unknown threads or from external debuggers.
 * It runs in a dedicated thread.
 */
void *
task_exception_catcher(
	void	*arg)
{
	struct server_thread_priv_data	priv_data;
	kern_return_t			kr;
#define MSG_BUFFER_SIZE	8192
	union request_msg {
		mach_msg_header_t	hdr;
		mig_reply_error_t	death_pill;
		char			space[MSG_BUFFER_SIZE];
	} *msg_buffer_1, *msg_buffer_2;
	mach_msg_header_t		*request;
	mig_reply_error_t		*reply;
	mach_msg_header_t		*tmp;

	cthread_set_name(cthread_self(), "task exc catcher");
	server_thread_set_priv_data(cthread_self(), &priv_data);

	uniproc_enter();

	kr = vm_allocate(mach_task_self(),
			 (vm_address_t *) &msg_buffer_1,
			 2 * sizeof *msg_buffer_1,
			 TRUE);
	if (kr != KERN_SUCCESS) {
		MACH3_DEBUG(0, kr, ("task_exception_catcher: vm_allocate"));
		panic("task_exception_catcher");
	}

	msg_buffer_2 = msg_buffer_1 + 1;
	request = &msg_buffer_1->hdr;
	reply = &msg_buffer_2->death_pill;

	do {
		uniproc_exit();
		kr = mach_msg(request, MACH_RCV_MSG,
			      0, sizeof *msg_buffer_1,
			      user_trap_port,
			      MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
		if (kr != MACH_MSG_SUCCESS) {
			MACH3_DEBUG(1, kr,
				    ("task_exception_catcher: mach_msg"));
			panic("task_exception_catcher: receive");
		}
		uniproc_enter();

		if (exc_server(request, &reply->Head)) {}
		else {
			printk("trap_exception_catcher: invalid message"
			       "(id = %d = 0x%x)\n",
			       request->msgh_id, request->msgh_id);
		}

		if (reply->Head.msgh_remote_port == MACH_PORT_NULL) {
			/* no reply port, just get another request */
			continue;
		}
		if (!(reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
		    reply->RetCode == MIG_NO_REPLY) {
			/* deallocate reply port right */
			(void) mach_port_deallocate(mach_task_self(),
						    reply->Head.msgh_remote_port);
			continue;
		}

		/* Send reply to request and receive another */
		uniproc_exit();
		kr = mach_msg(&reply->Head,
			      MACH_SEND_MSG,
			      reply->Head.msgh_size,
			      0,
			      MACH_PORT_NULL,
			      MACH_MSG_TIMEOUT_NONE,
			      MACH_PORT_NULL);
		uniproc_enter();

		if (kr != MACH_MSG_SUCCESS) {
			if (kr == MACH_SEND_INVALID_DEST) {
				/* deallocate reply port right */
				/* XXX should destroy reply msg */
				(void) mach_port_deallocate(mach_task_self(),
							    reply->Head.msgh_remote_port);
			} else {
				MACH3_DEBUG(0, kr, ("mach_msg"));
				panic("task_exception_catcher: send");
			}
		}

		tmp = request;
		request = (mach_msg_header_t *) reply;
		reply = (mig_reply_error_t *) tmp;

	} while (1);
       
	cthread_detach(cthread_self());
	cthread_exit((void *) 0);
	/*NOTREACHED*/
	return (void *) 0;
}
Пример #11
0
/*++
Function :
    SEHExceptionThread

    Entry point for the thread that will listen for exception in any other thread.

Parameters :
    void *args - not used

Return value :
   Never returns
--*/
void *SEHExceptionThread(void *args)
{
    mach_msg_return_t MachRet;

    // Handle exceptions forever.
    while (1)
    {
        char buf[512];
        mach_msg_header_t *msg = (mach_msg_header_t *)buf;
        MachRet = mach_msg(msg,
                           MACH_RCV_MSG | MACH_RCV_LARGE,
                           0,
                           sizeof(buf),
                           s_ExceptionPort,
                           MACH_MSG_TIMEOUT_NONE,
                           MACH_PORT_NULL);

        if (MachRet == MACH_RCV_TOO_LARGE)
        {
            UTIL_SetLastErrorFromMach(MachRet);
            ExitProcess(GetLastError());
        }

        if (MachRet != MACH_MSG_SUCCESS)
        {
            UTIL_SetLastErrorFromMach(MachRet);
            ExitProcess(GetLastError());
        }

        if (msg->msgh_id == SET_THREAD_MESSAGE_ID)
        {
            MSG_SET_THREAD *MsgSet = (MSG_SET_THREAD *)msg;

            MachRet = thread_suspend(MsgSet->m_ThreadPort);

            if (MachRet != KERN_SUCCESS)
            {
                UTIL_SetLastErrorFromMach(MachRet);
                ExitProcess(GetLastError());
            }
            if (!CONTEXT_SetThreadContextOnPort(MsgSet->m_ThreadPort, &MsgSet->m_ThreadContext))
            {
                ExitProcess(GetLastError());
            }

            MachRet = thread_resume(MsgSet->m_ThreadPort);
            if (MachRet != KERN_SUCCESS)
            {
                UTIL_SetLastErrorFromMach(MachRet);
                ExitProcess(GetLastError());
            }
        }
        else
        {
            char *MsgReply[512];
            mach_msg_header_t *reply = (mach_msg_header_t *)MsgReply;

            // Pass the message to exc_server which in turn calls catch_exception_raise
            exc_server(msg, reply);

            // Send the reply message back
            MachRet = mach_msg(reply,
                            MACH_SEND_MSG | MACH_MSG_OPTION_NONE,
                            reply->msgh_size,
                            0,
                            MACH_PORT_NULL,
                            MACH_MSG_TIMEOUT_NONE,
                            MACH_PORT_NULL);

            if (MachRet != KERN_SUCCESS)
            {
                UTIL_SetLastErrorFromMach(MachRet);
                ExitProcess(GetLastError());
            }
        }        
    } // Check for more errors

}
Пример #12
0
/* The main function of the thread listening for exceptions.  */
static void *
mach_exception_thread (void *arg)
{
  for (;;)
    {
      /* These two structures contain some private kernel data. We don't need
         to access any of it so we don't bother defining a proper struct. The
         correct definitions are in the xnu source code. */
      /* Buffer for a message to be received.  */
      struct
        {
          mach_msg_header_t head;
          mach_msg_body_t msgh_body;
          char data[1024];
        }
        msg;
      /* Buffer for a reply message.  */
      struct
        {
          mach_msg_header_t head;
          char data[1024];
        }
        reply;

      mach_msg_return_t retval;

#ifdef DEBUG_EXCEPTION_HANDLING
      fprintf (stderr, "Exception thread going to sleep\n");
#endif

      /* Wait for a message on the exception port.  */
      retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0,
                         sizeof (msg), our_exception_port,
                         MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
#ifdef DEBUG_EXCEPTION_HANDLING
      fprintf (stderr, "Exception thread woke up\n");
#endif
      if (retval != MACH_MSG_SUCCESS)
        {
#ifdef DEBUG_EXCEPTION_HANDLING
          fprintf (stderr, "mach_msg receive failed with %d %s\n",
                   (int) retval, mach_error_string (retval));
#endif
          abort ();
        }

      /* Handle the message: Call exc_server, which will call
         catch_exception_raise and produce a reply message.  */
#ifdef DEBUG_EXCEPTION_HANDLING
      fprintf (stderr, "Calling exc_server\n");
#endif
      exc_server (&msg.head, &reply.head);
#ifdef DEBUG_EXCEPTION_HANDLING
      fprintf (stderr, "Finished exc_server\n");
#endif

      /* Send the reply.  */
      if (mach_msg (&reply.head, MACH_SEND_MSG, reply.head.msgh_size,
                    0, MACH_PORT_NULL,
                    MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)
          != MACH_MSG_SUCCESS)
        {
#ifdef DEBUG_EXCEPTION_HANDLING
          fprintf (stderr, "mach_msg send failed\n");
#endif
          abort ();
        }
#ifdef DEBUG_EXCEPTION_HANDLING
      fprintf (stderr, "Reply successful\n");
#endif
    }
}