+
+ ret = task_get_exception_ports(taskinfo->task, EXC_MASK_ALL, taskinfo->exceptionInfo.masks, &taskinfo->exceptionInfo.count, taskinfo->exceptionInfo.ports, taskinfo->exceptionInfo.behaviors, taskinfo->exceptionInfo.flavors);
+
+ if (ret != KERN_SUCCESS) {
+ fprintf(stderr, "task_get_exception_ports() failed: pid:%d error: %s\n",taskinfo->pid, mach_error_string(ret));
+ taskinfo->pid = 0;
+ }
+
+ /* collect threads port as well */
+ taskinfo->threadCount = 0;
+ thread_act_array_t threadPorts;
+ ret = task_threads(taskinfo->task, &threadPorts, &taskinfo->threadCount);
+
+ if (ret != KERN_SUCCESS) {
+ fprintf(stderr, "task_threads() failed: pid:%d error: %s\n",taskinfo->pid, mach_error_string(ret));
+ taskinfo->threadCount = 0;
+ } else {
+ /* collect the thread information */
+ taskinfo->threadInfos = (struct my_per_thread_info *)malloc(sizeof(struct my_per_thread_info) * taskinfo->threadCount);
+ bzero(taskinfo->threadInfos, sizeof(struct my_per_thread_info) * taskinfo->threadCount);
+
+ /* now collect exception ports for each of those threads as well */
+ taskinfo->threadExceptionInfos = (struct exc_port_info *) malloc(sizeof(struct exc_port_info) * taskinfo->threadCount);
+ boolean_t found_exception = false;
+ for (int i = 0; i < taskinfo->threadCount; i++) {
+ unsigned th_kobject = 0;
+ unsigned th_kotype = 0;
+ ipc_voucher_t th_voucher = IPC_VOUCHER_NULL;
+ thread_identifier_info_data_t th_info;
+ mach_msg_type_number_t th_info_count = THREAD_IDENTIFIER_INFO_COUNT;
+ struct exc_port_info *excinfo = &(taskinfo->threadExceptionInfos[i]);
+
+ ret = thread_get_exception_ports(threadPorts[i], EXC_MASK_ALL, excinfo->masks, &excinfo->count, excinfo->ports, excinfo->behaviors, excinfo->flavors);
+ if (ret != KERN_SUCCESS){
+ fprintf(stderr, "thread_get_exception_ports() failed: pid: %d thread: %d error %s\n", taskinfo->pid, threadPorts[i], mach_error_string(ret));
+ }
+
+ if (excinfo->count != 0) {
+ found_exception = true;
+ }
+
+ taskinfo->threadInfos[i].thread = threadPorts[i];
+
+ if (KERN_SUCCESS == mach_port_kernel_object(mach_task_self(), threadPorts[i], &th_kotype, &th_kobject)) {
+ taskinfo->threadInfos[i].th_kobject = th_kobject;
+ if (KERN_SUCCESS == thread_info(threadPorts[i], THREAD_IDENTIFIER_INFO, (thread_info_t)&th_info, &th_info_count)) {
+ taskinfo->threadInfos[i].th_id = th_info.thread_id;
+ }
+ }
+
+ if (KERN_SUCCESS == thread_get_mach_voucher(threadPorts[i], 0, &th_voucher) && th_voucher != IPC_VOUCHER_NULL) {
+ char *detail = copy_voucher_detail(mach_task_self(), th_voucher, NULL);
+ taskinfo->threadInfos[i].voucher_detail = strndup(detail, VOUCHER_DETAIL_MAXLEN);
+ free(detail);
+
+ mach_port_deallocate(mach_task_self(), th_voucher);
+ }
+
+ mach_port_deallocate(mach_task_self(), threadPorts[i]);
+ threadPorts[i] = MACH_PORT_NULL;
+ }
+
+ if (found_exception == false) {
+ free(taskinfo->threadExceptionInfos);
+ taskinfo->threadExceptionInfos = NULL;
+ }
+
+ }
+
+ vm_deallocate(mach_task_self(), threadPorts, taskinfo->threadCount * sizeof(thread_act_t));
+ threadPorts = NULL;
+
+ ret = mach_port_space_info(target_task, &taskinfo->info, &taskinfo->table, &taskinfo->tableCount, &taskinfo->tree, &taskinfo->treeCount);
+