示例#1
0
bool
MachException::Message::CatchExceptionRaise()
{
    bool success = false;
    // locker will keep a mutex locked until it goes out of scope
//    PThreadMutex::Locker locker(&g_message_mutex);
    //    DNBLogThreaded("calling  mach_exc_server");
    g_message = &state;
    // The exc_server function is the MIG generated server handling function
    // to handle messages from the kernel relating to the occurrence of an
    // exception in a thread. Such messages are delivered to the exception port
    // set via thread_set_exception_ports or task_set_exception_ports. When an
    // exception occurs in a thread, the thread sends an exception message to
    // its exception port, blocking in the kernel waiting for the receipt of a
    // reply. The exc_server function performs all necessary argument handling
    // for this kernel message and calls catch_exception_raise,
    // catch_exception_raise_state or catch_exception_raise_state_identity,
    // which should handle the exception. If the called routine returns
    // KERN_SUCCESS, a reply message will be sent, allowing the thread to
    // continue from the point of the exception; otherwise, no reply message
    // is sent and the called routine must have dealt with the exception
    // thread directly.
    if (mach_exc_server (&exc_msg.hdr, &reply_msg.hdr))
    {
        success = true;
    }
    else if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
    {
        DNBLogThreaded("mach_exc_server returned zero...");
    }
    g_message = NULL;
    return success;
}
示例#2
0
static void* exception_server (mach_port_t exceptionPort) {
    mach_msg_return_t rt;
    mach_msg_header_t *msg;
    mach_msg_header_t *reply;

    msg   = safe_malloc(sizeof(union __RequestUnion__mach_exc_subsystem));
    reply = safe_malloc(sizeof(union __ReplyUnion__mach_exc_subsystem));

    while (1) {
         rt = mach_msg(msg, MACH_RCV_MSG, 0, sizeof(union __RequestUnion__mach_exc_subsystem), exceptionPort, 0, MACH_PORT_NULL);

         if (rt!= MACH_MSG_SUCCESS) {
            DEBUG_PRINT("[-exception_server] MACH_RCV_MSG stopped, exit from exception_server thread :%d\n", 1);
            return "MACH_RCV_MSG_FAILURE";
         }
         /*
          * Call out to the mach_exc_server generated by mig and mach_exc.defs.
          * This will in turn invoke one of:
          * mach_catch_exception_raise()
          * mach_catch_exception_raise_state()
          * mach_catch_exception_raise_state_identity()
          * .. depending on the behavior specified when registering the Mach exception port.
          */
         mach_exc_server(msg, reply);

         // Send the now-initialized reply
         rt = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);

         if (rt!= MACH_MSG_SUCCESS) {
            return "MACH_SEND_MSG_FAILURE";
         }
    }
}
示例#3
0
bool TargetException::run()
{
    m_stop = false;
    for (;;)
    {
        auto kr = mach_msg(&m_rcvMsg.head,
               MACH_RCV_MSG, 0,
               sizeof(m_rcvMsg), m_exceptionPort,
               MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);

        if (m_stop)
        {
            return true;
        }

        if (kr != MACH_MSG_SUCCESS)
        {
            log(QString("mach_msg rcv failde: %1").arg(mach_error_string(kr)), LogType::Error);
            return false;
        }

        /* Handle the message (calls catch_exception_raise) */
        // we should use mach_exc_server for 64bits
        if (mach_exc_server(&m_rcvMsg.head, &m_sendMsg.head) != TRUE)
        {
            log(QString("mach_exc_server failde"), LogType::Error);
            return false;
        }

        kr = mach_msg(&m_sendMsg.head, MACH_SEND_MSG,
                m_sendMsg.head.msgh_size, 0, MACH_PORT_NULL,
                MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
        if (kr != MACH_MSG_SUCCESS)
        {
            log(QString("mach_msg send failde: %1").arg(mach_error_string(kr)), LogType::Error);
            return false;
        }
    }
}
示例#4
0
static
void
ux_handler(void)
{
    task_t		self = current_task();
    mach_port_name_t	exc_port_name;
    mach_port_name_t	exc_set_name;

    /* self->kernel_vm_space = TRUE; */
    ux_handler_self = self;


    /*
     *	Allocate a port set that we will receive on.
     */
    if (mach_port_allocate(get_task_ipcspace(ux_handler_self), MACH_PORT_RIGHT_PORT_SET,  &exc_set_name) != MACH_MSG_SUCCESS)
	    panic("ux_handler: port_set_allocate failed");

    /*
     *	Allocate an exception port and use object_copyin to
     *	translate it to the global name.  Put it into the set.
     */
    if (mach_port_allocate(get_task_ipcspace(ux_handler_self), MACH_PORT_RIGHT_RECEIVE, &exc_port_name) != MACH_MSG_SUCCESS)
	panic("ux_handler: port_allocate failed");
    if (mach_port_move_member(get_task_ipcspace(ux_handler_self),
    			exc_port_name,  exc_set_name) != MACH_MSG_SUCCESS)
	panic("ux_handler: port_set_add failed");

    if (ipc_object_copyin(get_task_ipcspace(self), exc_port_name,
			MACH_MSG_TYPE_MAKE_SEND, 
			(void *) &ux_exception_port) != MACH_MSG_SUCCESS)
		panic("ux_handler: object_copyin(ux_exception_port) failed");

    proc_list_lock();
    thread_wakeup(&ux_exception_port);
    proc_list_unlock();

    /* Message handling loop. */

    for (;;) {
	struct rep_msg {
		mach_msg_header_t Head;
		NDR_record_t NDR;
		kern_return_t RetCode;
	} rep_msg;
	struct exc_msg {
		mach_msg_header_t Head;
		/* start of the kernel processed data */
		mach_msg_body_t msgh_body;
		mach_msg_port_descriptor_t thread;
		mach_msg_port_descriptor_t task;
		/* end of the kernel processed data */
		NDR_record_t NDR;
		exception_type_t exception;
		mach_msg_type_number_t codeCnt;
		mach_exception_data_t code;
		/* some times RCV_TO_LARGE probs */
		char pad[512];
	} exc_msg;
	mach_port_name_t	reply_port;
	kern_return_t	 result;

	exc_msg.Head.msgh_local_port = CAST_MACH_NAME_TO_PORT(exc_set_name);
	exc_msg.Head.msgh_size = sizeof (exc_msg);
#if 0
	result = mach_msg_receive(&exc_msg.Head);
#else
	result = mach_msg_receive(&exc_msg.Head, MACH_RCV_MSG,
			     sizeof (exc_msg), exc_set_name,
			     MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL,
			     0);
#endif
	if (result == MACH_MSG_SUCCESS) {
	    reply_port = CAST_MACH_PORT_TO_NAME(exc_msg.Head.msgh_remote_port);

	    if (mach_exc_server(&exc_msg.Head, &rep_msg.Head)) {
		result = mach_msg_send(&rep_msg.Head, MACH_SEND_MSG,
			sizeof (rep_msg),MACH_MSG_TIMEOUT_NONE,MACH_PORT_NULL);
		if (reply_port != 0 && result != MACH_MSG_SUCCESS)
			mach_port_deallocate(get_task_ipcspace(ux_handler_self), reply_port);
	    }

	}
	else if (result == MACH_RCV_TOO_LARGE)
		/* ignore oversized messages */;
	else
		panic("exception_handler");
    }
}