Ну, я понял.
Для обработки исключений маха, вы должны зарегистрировать порт маха для интересующих вас исключений. Затем вы ждете сообщения, поступающего на порт в другом потоке. Когда приходит сообщение, вы вызываете exc_server()
, реализация которого обеспечивается System.library. exec_server()
принимает поступившее сообщение и вызывает один из трех обработчиков, которые вы должны предоставить. catch_exception_raise()
, catch_exception_raise_state()
или catch_exception_raise_state_identity()
в зависимости от аргументов, которые вы передали task_set_exception_ports()
. Вот как это делается для 32-битных приложений.
Для 64-битных приложений 32-битный метод все еще работает, но данные, передаваемые вам в вашем обработчике, могут быть усечены до 32-битных. Чтобы получить 64-битные данные, передаваемые вашим обработчикам, требуется немного дополнительной работы, которая не очень прямолинейна и, насколько я могу судить, не очень хорошо документирована. Я наткнулся на решение, глядя на источники для GDB.
Вместо того, чтобы звонить exc_server()
, когда сообщение приходит в порт, вместо этого вы должны позвонить mach_exc_server()
. У обработчиков также должны быть разные имена catch_mach_exception_raise()
, catch_mach_exception_raise_state()
и catch_mach_exception_raise_state_identity()
. Параметры для обработчиков такие же, как у их 32-битных аналогов.
Проблема в том, что mach_exc_server()
не предоставлен вам, как exc_server()
. Чтобы получить реализацию для mach_exc_server()
, необходимо использовать утилиту MIG (Mach Interface Generator). MIG берет файл определения интерфейса и генерирует набор исходных файлов, которые включают в себя серверную функцию, которая отправляет сообщения mach на предоставляемые вами обработчики. SDK 10.5 и 10.6 включают файл определения MIG для сообщений об исключениях и генерируют функцию mach_exc_server()
. Затем вы включаете сгенерированные исходные файлы в свой проект, и тогда все готово.
Приятно то, что если вы нацелены на 10,6+ (и, возможно, на 10,5), вы можете использовать одинаковую обработку исключений как для 32, так и для 64 бит. Просто ИЛИ поведение исключения с MACH_EXCEPTION_CODES
, когда вы устанавливаете порты исключения. Коды исключений будут представлены как 64-битные значения, но вы можете урезать их до 32-битных в вашей 32-битной сборке.
Я взял файл mach_exc.defs
и скопировал его в исходный каталог, открыл терминал и использовал команду mig -v mach_exc.defs
. Это сгенерировало mach_exc.h
, mach_excServer.c
и mach_excUser.c
. Затем я включил эти файлы в свой проект, добавил правильное объявление для функции сервера в исходный файл и реализовал мои обработчики. Затем я собрал свое приложение и был готов к работе.
Ну, это не лучшее описание, но, надеюсь, это поможет кому-то еще.