mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-17 04:39:34 +00:00
Improve stability on non-jailbroken devices
By setting up a Mach exception handler, we can try to handle most signals before they cause the system to hang. Since PT_TRACE_ME enables CS_DEBUGGED on the parent process as well, we can simplify some of the code as well.
This commit is contained in:
parent
6610cd7663
commit
99c631c791
@ -105,4 +105,8 @@
|
||||
NativeMessageReceived("got_focus", "");
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
#ifndef _SYS_CODESIGN_H_
|
||||
#define _SYS_CODESIGN_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/* code signing attributes of a process */
|
||||
#define CS_VALID 0x0001 /* dynamically valid */
|
||||
#define CS_HARD 0x0100 /* don't load invalid pages */
|
||||
#define CS_KILL 0x0200 /* kill process if it becomes invalid */
|
||||
#define CS_EXEC_SET_HARD 0x1000 /* set CS_HARD on any exec'ed process */
|
||||
#define CS_EXEC_SET_KILL 0x2000 /* set CS_KILL on any exec'ed process */
|
||||
#define CS_KILLED 0x10000 /* was killed by kernel for invalidity */
|
||||
#define CS_RESTRICT 0x20000 /* tell dyld to treat restricted */
|
||||
|
||||
/* csops operations */
|
||||
#define CS_OPS_STATUS 0 /* return status */
|
||||
#define CS_OPS_MARKINVALID 1 /* invalidate process */
|
||||
#define CS_OPS_MARKHARD 2 /* set HARD flag */
|
||||
#define CS_OPS_MARKKILL 3 /* set KILL flag (sticky) */
|
||||
#define CS_OPS_PIDPATH 4 /* get executable's pathname */
|
||||
#define CS_OPS_CDHASH 5 /* get code directory hash */
|
||||
#define CS_OPS_PIDOFFSET 6 /* get offset of active Mach-o slice */
|
||||
#define CS_OPS_ENTITLEMENTS_BLOB 7 /* get entitlements blob */
|
||||
#define CS_OPS_MARKRESTRICT 8 /* set RESTRICT flag (sticky) */
|
||||
|
||||
#ifndef KERNEL
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* code sign operations */
|
||||
int csops(pid_t pid, unsigned int ops, void * useraddr, size_t usersize);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* ! KERNEL */
|
||||
|
||||
#endif /* _SYS_CODESIGN_H_ */
|
94
ios/main.mm
94
ios/main.mm
@ -1,12 +1,14 @@
|
||||
// main.mm boilerplate
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <dlfcn.h>
|
||||
#import <mach/mach.h>
|
||||
#import <pthread.h>
|
||||
#import <string>
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
#import <sys/syscall.h>
|
||||
#import <AudioToolbox/AudioToolbox.h>
|
||||
#import "codesign.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "PPSSPPUIApplication.h"
|
||||
@ -15,53 +17,33 @@
|
||||
#include "base/NativeApp.h"
|
||||
#include "profiler/profiler.h"
|
||||
|
||||
#define CS_OPS_STATUS 0 /* return status */
|
||||
#define CS_DEBUGGED 0x10000000 /* process is currently or has previously been debugged and allowed to run with invalid pages */
|
||||
#define PTRACE_TRACEME 0 /* Indicate that this process is to be traced by its parent. */
|
||||
#define PT_ATTACHEXC 14 /* attach to running process with signal exception */
|
||||
#define PT_DETACH 11 /* stop tracing a process */
|
||||
int csops(pid_t pid, unsigned int ops, void * useraddr, size_t usersize);
|
||||
#define ptrace(a, b, c, d) syscall(SYS_ptrace, a, b, c, d)
|
||||
#define CS_OPS_STATUS 0 /* return status */
|
||||
#define CS_DEBUGGED 0x10000000 /* process is currently or has previously been debugged and allowed to run with invalid pages */
|
||||
#define PT_TRACE_ME 0 /* child declares it's being traced */
|
||||
#define PT_SIGEXC 12 /* signals as exceptions for current_proc */
|
||||
|
||||
bool get_debugged() {
|
||||
static int (*csops)(pid_t pid, unsigned int ops, void * useraddr, size_t usersize);
|
||||
static boolean_t (*exc_server)(mach_msg_header_t *, mach_msg_header_t *);
|
||||
static int (*ptrace)(int request, pid_t pid, caddr_t addr, int data);
|
||||
|
||||
bool cs_debugged() {
|
||||
int flags;
|
||||
int rv = csops(getpid(), CS_OPS_STATUS, &flags, sizeof(flags));
|
||||
if (rv==0 && flags&CS_DEBUGGED) return true;
|
||||
return !csops(getpid(), CS_OPS_STATUS, &flags, sizeof(flags)) && flags & CS_DEBUGGED;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid > 0) {
|
||||
int st,rv,i=0;
|
||||
do {
|
||||
usleep(500);
|
||||
rv = waitpid(pid, &st, 0);
|
||||
} while (rv<0 && i++<10);
|
||||
if (rv<0) fprintf(stderr, "Unable to wait for child?\n");
|
||||
} else if (pid == 0) {
|
||||
pid_t ppid = getppid();
|
||||
int rv = ptrace(PT_ATTACHEXC, ppid, 0, 0);
|
||||
if (rv) {
|
||||
perror("Unable to attach to process");
|
||||
exit(1);
|
||||
}
|
||||
for (int i=0; i<100; i++) {
|
||||
usleep(1000);
|
||||
errno = 0;
|
||||
rv = ptrace(PT_DETACH, ppid, 0, 0);
|
||||
if (rv==0) break;
|
||||
}
|
||||
if (rv) {
|
||||
perror("Unable to detach from process");
|
||||
exit(1);
|
||||
}
|
||||
exit(0);
|
||||
} else {
|
||||
perror("Unable to fork");
|
||||
}
|
||||
kern_return_t catch_exception_raise(mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t code_count) {
|
||||
return KERN_FAILURE;
|
||||
}
|
||||
|
||||
rv = csops(getpid(), CS_OPS_STATUS, &flags, sizeof(flags));
|
||||
if (rv==0 && flags&CS_DEBUGGED) return true;
|
||||
|
||||
return false;
|
||||
void *exception_handler(void *argument) {
|
||||
auto port = *reinterpret_cast<mach_port_t *>(argument);
|
||||
mach_msg_server(exc_server, 2048, port, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -185,10 +167,28 @@ void Vibrate(int mode) {
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
csops = reinterpret_cast<decltype(csops)>(dlsym(dlopen(nullptr, RTLD_LAZY), "csops"));
|
||||
exc_server = reinterpret_cast<decltype(exc_server)>(dlsym(dlopen(NULL, RTLD_LAZY), "exc_server"));
|
||||
ptrace = reinterpret_cast<decltype(ptrace)>(dlsym(dlopen(NULL, RTLD_LAZY), "ptrace"));
|
||||
// see https://github.com/hrydgard/ppsspp/issues/11905
|
||||
if (!get_debugged()) {
|
||||
fprintf(stderr, "Unable to cleanly obtain CS_DEBUGGED - probably not jailbroken. Attempting old method.\n");
|
||||
ptrace(PTRACE_TRACEME, 0, 0, 0);
|
||||
if (!cs_debugged()) {
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
ptrace(PT_TRACE_ME, 0, nullptr, 0);
|
||||
exit(0);
|
||||
} else if (pid < 0) {
|
||||
perror("Unable to fork");
|
||||
|
||||
ptrace(PT_TRACE_ME, 0, nullptr, 0);
|
||||
ptrace(PT_SIGEXC, 0, nullptr, 0);
|
||||
|
||||
mach_port_t port = MACH_PORT_NULL;
|
||||
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
|
||||
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
task_set_exception_ports(mach_task_self(), EXC_MASK_SOFTWARE, port, EXCEPTION_DEFAULT, THREAD_STATE_NONE);
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, nullptr, exception_handler, reinterpret_cast<void *>(&port));
|
||||
}
|
||||
}
|
||||
|
||||
PROFILE_INIT();
|
||||
|
Loading…
x
Reference in New Issue
Block a user