Skip to content

Commit f91b5d8

Browse files
ohaiibuzzleviatearz
authored andcommitted
Insomnia hack (PlayCover#211)
* test: insomnia hack * fix: allow sleep spamming block to be togglable from PlayCover (cherry picked from commit ef86a6c)
1 parent 4785ebc commit f91b5d8

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

PlayTools/PlayLoader.m

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// PlayTools
44
//
55

6+
#include <Foundation/Foundation.h>
67
#include <errno.h>
78
#include <sys/sysctl.h>
89

@@ -211,10 +212,72 @@ static OSStatus pt_SecItemDelete(CFDictionaryRef query) {
211212
DYLD_INTERPOSE(pt_SecItemUpdate, SecItemUpdate)
212213
DYLD_INTERPOSE(pt_SecItemDelete, SecItemDelete)
213214

215+
static NSMutableDictionary *thread_sleep_counters = nil;
216+
static NSMutableDictionary *last_sleep_attempts = nil;
217+
static dispatch_once_t thread_sleep_once;
218+
static NSLock *thread_sleep_lock = nil;
219+
220+
static int pt_usleep(useconds_t time) {
221+
dispatch_once(&thread_sleep_once, ^{
222+
thread_sleep_counters = [NSMutableDictionary dictionary];
223+
last_sleep_attempts = [NSMutableDictionary dictionary];
224+
thread_sleep_lock = [[NSLock alloc] init];
225+
[thread_sleep_lock lock];
226+
});
227+
228+
if ([[PlaySettings shared] blockSleepSpamming]) {
229+
int thread_id = pthread_mach_thread_np(pthread_self());
230+
NSNumber *threadKey = @(thread_id);
231+
232+
int thread_sleep_counter = [thread_sleep_counters[threadKey] intValue];
233+
int last_sleep_attempt = [last_sleep_attempts[threadKey] intValue];
234+
235+
if (time == 100000) {
236+
int timestamp = (int)[[NSDate date] timeIntervalSince1970];
237+
// If it sleeps too fast, increase counter
238+
if (timestamp - last_sleep_attempt < 2) {
239+
thread_sleep_counter++;
240+
} else {
241+
thread_sleep_counter = 1;
242+
}
243+
last_sleep_attempt = timestamp;
244+
thread_sleep_counters[threadKey] = @(thread_sleep_counter);
245+
last_sleep_attempts[threadKey] = @(last_sleep_attempt);
246+
247+
}
248+
249+
if (thread_sleep_counter > 100) {
250+
// Stop this thread from spamming usleep calls
251+
NSLog(@"[PC] Thread %i exceeded usleep limit. Seem sus, stopping this "
252+
@"thread FOREVER",
253+
thread_id);
254+
255+
[thread_sleep_lock lock];
256+
[thread_sleep_lock unlock];
257+
258+
return 0;
259+
}
260+
}
261+
262+
return usleep(time);
263+
}
264+
265+
DYLD_INTERPOSE(pt_usleep, usleep)
266+
214267
@implementation PlayLoader
215268

216269
static void __attribute__((constructor)) initialize(void) {
217270
[PlayCover launch];
271+
272+
if ([[PlaySettings shared] blockSleepSpamming]) {
273+
// Add an observer so we can unlock threads on app termination
274+
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillTerminateNotification
275+
object:nil
276+
queue:[NSOperationQueue mainQueue]
277+
usingBlock:^(NSNotification * _Nonnull note) {
278+
[thread_sleep_lock unlock];
279+
}];
280+
}
218281
}
219282

220283
@end

PlayTools/PlaySettings.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ let settings = PlaySettings.shared
8989
@objc lazy var noKMOnInput = settingsData.noKMOnInput
9090

9191
@objc lazy var enableScrollWheel = settingsData.enableScrollWheel
92+
93+
@objc var blockSleepSpamming = false
9294
}
9395

9496
struct AppSettingsData: Codable {

0 commit comments

Comments
 (0)