@@ -230,11 +230,58 @@ static int pt_unlink(char const* path) {
230230 return unlink (ue_fix_filename (path));
231231}
232232
233+ static NSMutableDictionary *thread_sleep_counters = nil ;
234+ static NSMutableDictionary *last_sleep_attempts = nil ;
235+ static dispatch_once_t thread_sleep_once;
236+
237+ static int pt_usleep (useconds_t time) {
238+ dispatch_once (&thread_sleep_once, ^{
239+ thread_sleep_counters = [NSMutableDictionary dictionary ];
240+ last_sleep_attempts = [NSMutableDictionary dictionary ];
241+ });
242+
243+ int thread_id = pthread_mach_thread_np (pthread_self ());
244+ NSNumber *threadKey = @(thread_id);
245+
246+ int thread_sleep_counter = [thread_sleep_counters[threadKey] intValue ];
247+ int last_sleep_attempt = [last_sleep_attempts[threadKey] intValue ];
248+
249+ NSLog (@" [PC] Thread %i called usleep(%u ) - count %i " , thread_id, time,
250+ thread_sleep_counter);
251+
252+ if (time == 100000 ) {
253+ int timestamp = (int )[[NSDate date ] timeIntervalSince1970 ];
254+ // If it sleeps too fast, increase counter
255+ if (timestamp - last_sleep_attempt < 2 ) {
256+ thread_sleep_counter++;
257+ } else {
258+ thread_sleep_counter = 0 ;
259+ }
260+ last_sleep_attempt = timestamp;
261+ thread_sleep_counters[threadKey] = @(thread_sleep_counter);
262+ last_sleep_attempts[threadKey] = @(last_sleep_attempt);
263+ }
264+
265+ if (thread_sleep_counter > 100 ) {
266+ // Stop this thread from spamming usleep calls
267+ NSLog (@" [PC] Thread %i exceeded usleep limit. Seem sus, stopping this "
268+ @" thread FOREVER" ,
269+ thread_id);
270+ while (1 ) {
271+ [NSThread sleepForTimeInterval: 1000 ];
272+ }
273+ return 0 ;
274+ }
275+
276+ return usleep (time);
277+ }
278+
233279DYLD_INTERPOSE (pt_open, open)
234280DYLD_INTERPOSE(pt_stat, stat)
235281DYLD_INTERPOSE(pt_access, access)
236282DYLD_INTERPOSE(pt_rename, rename)
237283DYLD_INTERPOSE(pt_unlink, unlink)
284+ DYLD_INTERPOSE(pt_usleep, usleep)
238285
239286@implementation PlayLoader
240287
0 commit comments