bool MachTask::StartExceptionThread(DNBError &err) { DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( )", __FUNCTION__); task_t task = TaskPortForProcessID(err); if (MachTask::IsValid(task)) { // Got the mach port for the current process mach_port_t task_self = mach_task_self (); // Allocate an exception port that we will use to track our child process err = ::mach_port_allocate (task_self, MACH_PORT_RIGHT_RECEIVE, &m_exception_port); if (err.Fail()) return false; // Add the ability to send messages on the new exception port err = ::mach_port_insert_right (task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND); if (err.Fail()) return false; // Save the original state of the exception ports for our child process SaveExceptionPortInfo(); // We weren't able to save the info for our exception ports, we must stop... if (m_exc_port_info.mask == 0) { err.SetErrorString("failed to get exception port info"); return false; } // Set the ability to get all exceptions on this port err = ::task_set_exception_ports (task, m_exc_port_info.mask, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) { err.LogThreaded("::task_set_exception_ports ( task = 0x%4.4x, exception_mask = 0x%8.8x, new_port = 0x%4.4x, behavior = 0x%8.8x, new_flavor = 0x%8.8x )", task, m_exc_port_info.mask, m_exception_port, (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), THREAD_STATE_NONE); } if (err.Fail()) return false; // Create the exception thread err = ::pthread_create (&m_exception_thread, NULL, MachTask::ExceptionThread, this); return err.Success(); } else { DNBLogError("MachTask::%s (): task invalid, exception thread start failed.", __FUNCTION__); } return false; }
bool MachTask::StartExceptionThread(DNBError &err) { DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( )", __FUNCTION__); task_t task = TaskPortForProcessID(err); if (MachTask::IsValid(task)) { // Got the mach port for the current process mach_port_t task_self = mach_task_self (); // Allocate an exception port that we will use to track our child process err = ::mach_port_allocate (task_self, MACH_PORT_RIGHT_RECEIVE, &m_exception_port); if (err.Fail()) return false; // Add the ability to send messages on the new exception port err = ::mach_port_insert_right (task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND); if (err.Fail()) return false; // Save the original state of the exception ports for our child process SaveExceptionPortInfo(); // Set the ability to get all exceptions on this port err = ::task_set_exception_ports (task, EXC_MASK_ALL, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); if (err.Fail()) return false; // Create the exception thread err = ::pthread_create (&m_exception_thread, NULL, MachTask::ExceptionThread, this); return err.Success(); } else { DNBLogError("MachTask::%s (): task invalid, exception thread start failed.", __FUNCTION__); } return false; }
int ListApplications(std::string& plist, bool opt_runningApps, bool opt_debuggable) { #ifdef WITH_SPRINGBOARD int result = -1; CFAllocatorRef alloc = kCFAllocatorDefault; // Create a mutable array that we can populate. Specify zero so it can be of any size. CFReleaser<CFMutableArrayRef> plistMutableArray (::CFArrayCreateMutable (alloc, 0, &kCFTypeArrayCallBacks)); CFReleaser<CFStringRef> sbsFrontAppID (::SBSCopyFrontmostApplicationDisplayIdentifier ()); CFReleaser<CFArrayRef> sbsAppIDs (::SBSCopyApplicationDisplayIdentifiers (opt_runningApps, opt_debuggable)); // Need to check the return value from SBSCopyApplicationDisplayIdentifiers. CFIndex count = sbsAppIDs.get() ? ::CFArrayGetCount (sbsAppIDs.get()) : 0; CFIndex i = 0; for (i = 0; i < count; i++) { CFStringRef displayIdentifier = (CFStringRef)::CFArrayGetValueAtIndex (sbsAppIDs.get(), i); // Create a new mutable dictionary for each application CFReleaser<CFMutableDictionaryRef> appInfoDict (::CFDictionaryCreateMutable (alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); // Get the process id for the app (if there is one) pid_t pid = INVALID_NUB_PROCESS; if (::SBSProcessIDForDisplayIdentifier ((CFStringRef)displayIdentifier, &pid) == true) { CFReleaser<CFNumberRef> pidCFNumber (::CFNumberCreate (alloc, kCFNumberSInt32Type, &pid)); ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PID_KEY, pidCFNumber.get()); } // Set the a boolean to indicate if this is the front most if (sbsFrontAppID.get() && displayIdentifier && (::CFStringCompare (sbsFrontAppID.get(), displayIdentifier, 0) == kCFCompareEqualTo)) ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanTrue); else ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanFalse); CFReleaser<CFStringRef> executablePath (::SBSCopyExecutablePathForDisplayIdentifier (displayIdentifier)); if (executablePath.get() != NULL) { ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PATH_KEY, executablePath.get()); } CFReleaser<CFStringRef> iconImagePath (::SBSCopyIconImagePathForDisplayIdentifier (displayIdentifier)) ; if (iconImagePath.get() != NULL) { ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_ICON_PATH_KEY, iconImagePath.get()); } CFReleaser<CFStringRef> localizedDisplayName (::SBSCopyLocalizedApplicationNameForDisplayIdentifier (displayIdentifier)); if (localizedDisplayName.get() != NULL) { ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_DISPLAY_NAME_KEY, localizedDisplayName.get()); } // Append the application info to the plist array ::CFArrayAppendValue (plistMutableArray.get(), appInfoDict.get()); } CFReleaser<CFDataRef> plistData (::CFPropertyListCreateXMLData (alloc, plistMutableArray.get())); // write plist to service port if (plistData.get() != NULL) { CFIndex size = ::CFDataGetLength (plistData.get()); const UInt8 *bytes = ::CFDataGetBytePtr (plistData.get()); if (bytes != NULL && size > 0) { plist.assign((char *)bytes, size); return 0; // Success } else { DNBLogError("empty application property list."); result = -2; } } else { DNBLogError("serializing task list."); result = -3; } return result; #else // TODO: list all current processes DNBLogError("SBS doesn't support getting application list."); return -1; #endif }