From 4ba8384929e3c964822978a79fbbfc71117ac266 Mon Sep 17 00:00:00 2001 From: Mousen Date: Wed, 10 Dec 2025 04:39:26 +0500 Subject: [PATCH] Revert "Prevent iOS daemon throttling with SSH launch and priority boosts" This reverts commit 6d5d143dd983e7169c14cbd798a84fd99389efa6. --- screendump/FrameUpdater.m | 88 +++---------------- screendump/Makefile | 19 ++-- screendump/ScreenDumpVNC.m | 20 ----- screendump/layout/DEBIAN/postinst | 39 +------- .../com.mousen.screendumpd.plist | 16 ---- screendump/main.m | 32 ------- 6 files changed, 20 insertions(+), 194 deletions(-) diff --git a/screendump/FrameUpdater.m b/screendump/FrameUpdater.m index b12f40a..f81b864 100644 --- a/screendump/FrameUpdater.m +++ b/screendump/FrameUpdater.m @@ -1,5 +1,4 @@ #import "FrameUpdater.h" -#import @implementation FrameUpdater { @@ -7,7 +6,6 @@ NSOperationQueue *_q; BOOL _updatingFrames; CADisplayLink *_displayLink; - dispatch_source_t _timer; // Shared from ScreenDumpVNC IOSurfaceRef _screenSurface; @@ -22,14 +20,6 @@ // Dual capture mode support IOSurfaceRef _renderServerSurface; // Separate surface for CARenderServer (avoids framebuffer locking) CaptureMode(^_captureModeBlock)(void); - - // Diagnostics - uint64_t _timerFires; - uint64_t _framesRendered; - uint64_t _framesSkipped; - uint64_t _lastStatsTime; - uint64_t _totalCaptureTime; - uint64_t _maxCaptureTime; } -(instancetype)initWithSurfaceInfo:(IOSurfaceRef)screenSurface @@ -45,7 +35,6 @@ if ((self = [super init])) { _q = [[NSOperationQueue alloc] init]; _q.maxConcurrentOperationCount = 1; // Serialize to prevent frame queue buildup - _q.qualityOfService = NSQualityOfServiceUserInteractive; _updatingFrames = NO; _displayLink = nil; @@ -71,19 +60,12 @@ return; } - _timerFires++; - // Skip if queue is busy to prevent frame buildup and reduce lock contention if (_q.operationCount > 0) { - _framesSkipped++; return; } [_q addOperationWithBlock: ^{ - _framesRendered++; - - uint64_t captureStart = mach_absolute_time(); - // Get current capture mode CaptureMode mode = _captureModeBlock ? _captureModeBlock() : CaptureModeCARenderServer; BOOL needsScaling = (_width != _nativeWidth || _height != _nativeHeight); @@ -104,78 +86,28 @@ } } - uint64_t captureEnd = mach_absolute_time(); - uint64_t captureDuration = captureEnd - captureStart; - _totalCaptureTime += captureDuration; - if (captureDuration > _maxCaptureTime) _maxCaptureTime = captureDuration; - rfbMarkRectAsModified(_rfbScreenInfo, 0, 0, _width, _height); - - // Log stats every second - uint64_t now = mach_absolute_time(); - if (_lastStatsTime == 0) _lastStatsTime = now; - - mach_timebase_info_data_t timebase; - mach_timebase_info(&timebase); - uint64_t elapsed_ns = (now - _lastStatsTime) * timebase.numer / timebase.denom; - - if (elapsed_ns >= NSEC_PER_SEC) { - double elapsed_sec = (double)elapsed_ns / NSEC_PER_SEC; - double avgCaptureMs = (_framesRendered > 0) ? - ((double)_totalCaptureTime * timebase.numer / timebase.denom / _framesRendered / 1000000.0) : 0; - double maxCaptureMs = (double)_maxCaptureTime * timebase.numer / timebase.denom / 1000000.0; - - NSLog(@"[FPS] fps=%.1f skip=%.0f%% | capture: avg=%.1fms max=%.1fms", - _framesRendered / elapsed_sec, - (_timerFires > 0) ? (100.0 * _framesSkipped / _timerFires) : 0.0, - avgCaptureMs, maxCaptureMs); - _timerFires = 0; - _framesRendered = 0; - _framesSkipped = 0; - _totalCaptureTime = 0; - _maxCaptureTime = 0; - _lastStatsTime = now; - } }]; } -(void)stopFrameLoop { - _updatingFrames = NO; + if (_displayLink == nil) return; - if (_timer) { - dispatch_source_cancel(_timer); - _timer = nil; - } - - if (_displayLink) { - dispatch_async(dispatch_get_main_queue(), ^(void){ - [_displayLink invalidate]; - _displayLink = nil; - }); - } + dispatch_async(dispatch_get_main_queue(), ^(void){ + [_displayLink invalidate]; + _displayLink = nil; + _updatingFrames = NO; + }); } -(void)startFrameLoop { [self stopFrameLoop]; _updatingFrames = YES; - // Use high-priority dispatch timer instead of CADisplayLink - // CADisplayLink may be throttled for daemon processes - dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class( - DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INTERACTIVE, 0); - dispatch_queue_t timerQueue = dispatch_queue_create("com.mousen.screendump.frametimer", attr); - - _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, timerQueue); - - // 60 FPS = ~16.67ms interval - uint64_t interval = NSEC_PER_SEC / 60; - dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), interval, 0); - - dispatch_source_set_event_handler(_timer, ^{ - [self _updateFrame]; - }); - - dispatch_resume(_timer); + CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_updateFrame)]; + displayLink.preferredFramesPerSecond = 60; // Limit to 60 FPS + [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; + _displayLink = displayLink; } -(void)dealloc { diff --git a/screendump/Makefile b/screendump/Makefile index 8d2e689..3fa56e1 100644 --- a/screendump/Makefile +++ b/screendump/Makefile @@ -2,20 +2,19 @@ export THEOS_PACKAGE_SCHEME = rootless export ARCHS = arm64 export TARGET = iphone:16.5:14.0 export GO_EASY_ON_ME = 1 -export COPYFILE_DISABLE = 1 +export COPYFILE_DISABLE=1 include $(THEOS)/makefiles/common.mk TOOL_NAME = screendumpd - -screendumpd_FILES = $(wildcard *.m) -screendumpd_FRAMEWORKS = IOSurface IOKit -screendumpd_PRIVATE_FRAMEWORKS = IOMobileFramebuffer IOSurface -screendumpd_OBJCFLAGS = -I./vncbuild/include -Iinclude -fobjc-arc -screendumpd_LDFLAGS = -Wl,-segalign,4000 -L./vncbuild/lib -lvncserver -lpng -llzo2 -ljpeg -lssl -lcrypto -lz -screendumpd_CFLAGS = -w -screendumpd_CODESIGN_FLAGS = -Sen.plist -screendumpd_INSTALL_PATH = /usr/libexec +$(TOOL_NAME)_FILES = $(wildcard *.m) +$(TOOL_NAME)_FRAMEWORKS := IOSurface IOKit +$(TOOL_NAME)_PRIVATE_FRAMEWORKS := IOMobileFramebuffer IOSurface +$(TOOL_NAME)_OBJCFLAGS += -I./vncbuild/include -Iinclude -fobjc-arc +$(TOOL_NAME)_LDFLAGS += -Wl,-segalign,4000 -L./vncbuild/lib -lvncserver -lpng -llzo2 -ljpeg -lssl -lcrypto -lz +$(TOOL_NAME)_CFLAGS = -w +$(TOOL_NAME)_CODESIGN_FLAGS = "-Sen.plist" +$(TOOL_NAME)_INSTALL_PATH = /usr/libexec before-stage:: $(ECHO_NOTHING)find . -name '.DS_Store' -type f -delete$(ECHO_END) diff --git a/screendump/ScreenDumpVNC.m b/screendump/ScreenDumpVNC.m index 25d8e34..8b25594 100644 --- a/screendump/ScreenDumpVNC.m +++ b/screendump/ScreenDumpVNC.m @@ -5,7 +5,6 @@ #import #import #import "IOMobileFramebuffer.h" -#import @implementation ScreenDumpVNC { int _prefsHeight; @@ -39,25 +38,6 @@ +(void)load { ScreenDumpVNC* sharedInstance = [self sharedInstance]; if (![sharedInstance enabled]) return; - - // Tell iOS this is latency-critical work - prevents throttling for daemons - [[NSProcessInfo processInfo] beginActivityWithOptions:(NSActivityLatencyCritical | NSActivityUserInitiated) - reason:@"VNC screen streaming"]; - - // Power assertion to prevent display/GPU throttling - IOPMAssertionID assertionID; - IOPMAssertionCreateWithName(kIOPMAssertionTypePreventUserIdleDisplaySleep, - kIOPMAssertionLevelOn, - CFSTR("VNC screen capture requires display access"), - &assertionID); - - // Also assert we need system activity (prevents CPU throttling) - IOPMAssertionID systemAssertionID; - IOPMAssertionCreateWithName(kIOPMAssertionTypePreventUserIdleSystemSleep, - kIOPMAssertionLevelOn, - CFSTR("VNC server active"), - &systemAssertionID); - [sharedInstance setupScreenInfo]; [sharedInstance startVNCServer]; } diff --git a/screendump/layout/DEBIAN/postinst b/screendump/layout/DEBIAN/postinst index 24c3740..4cd0202 100755 --- a/screendump/layout/DEBIAN/postinst +++ b/screendump/layout/DEBIAN/postinst @@ -1,40 +1,3 @@ #!/bin/sh - -# Setup passwordless SSH for root to localhost (required for screendumpd performance) -SSH_DIR="/var/jb/var/root/.ssh" -KEY_FILE="$SSH_DIR/id_ed25519" -AUTH_KEYS="$SSH_DIR/authorized_keys" - -# Create .ssh directory if it doesn't exist -if [ ! -d "$SSH_DIR" ]; then - mkdir -p "$SSH_DIR" - chmod 700 "$SSH_DIR" -fi - -# Generate ed25519 key if it doesn't exist -if [ ! -f "$KEY_FILE" ]; then - ssh-keygen -t ed25519 -N "" -f "$KEY_FILE" -q - chmod 600 "$KEY_FILE" - chmod 644 "${KEY_FILE}.pub" -fi - -# Add public key to authorized_keys if not already present -if [ -f "${KEY_FILE}.pub" ]; then - PUB_KEY=$(cat "${KEY_FILE}.pub") - - # Create authorized_keys if it doesn't exist - if [ ! -f "$AUTH_KEYS" ]; then - touch "$AUTH_KEYS" - chmod 600 "$AUTH_KEYS" - fi - - # Check if key is already in authorized_keys - if ! grep -qF "$PUB_KEY" "$AUTH_KEYS" 2>/dev/null; then - echo "$PUB_KEY" >> "$AUTH_KEYS" - fi -fi - -# Load the launch daemon launchctl load /var/jb/Library/LaunchDaemons/com.mousen.screendumpd.plist 2> /dev/null - -exit 0 \ No newline at end of file +exit 0; \ No newline at end of file diff --git a/screendump/layout/Library/LaunchDaemons/com.mousen.screendumpd.plist b/screendump/layout/Library/LaunchDaemons/com.mousen.screendumpd.plist index ad6f616..82941bf 100644 --- a/screendump/layout/Library/LaunchDaemons/com.mousen.screendumpd.plist +++ b/screendump/layout/Library/LaunchDaemons/com.mousen.screendumpd.plist @@ -6,14 +6,6 @@ com.mousen.screendumpd ProgramArguments - /var/jb/usr/bin/ssh - -o - StrictHostKeyChecking=no - -o - UserKnownHostsFile=/dev/null - -o - BatchMode=yes - root@localhost /var/jb/usr/libexec/screendumpd RunAtLoad @@ -30,13 +22,5 @@ Core 9223372036854775807 - ProcessType - Interactive - Nice - -10 - LegacyTimers - - UserName - root diff --git a/screendump/main.m b/screendump/main.m index 894908c..1237af1 100644 --- a/screendump/main.m +++ b/screendump/main.m @@ -1,44 +1,12 @@ #import #import -#import -#import -#import -#import -#import #import "ScreenDumpVNC.h" #import "utils.h" #define kPreferencesNotify "com.mousen.screendump/restart" -static void signalHandler(int sig) { - exit(0); -} - int main(int argc, char *argv[], char *envp[]) { @autoreleasepool { - // Handle termination signals (sent by launchd or when SSH disconnects) - signal(SIGTERM, signalHandler); - signal(SIGHUP, signalHandler); - signal(SIGINT, signalHandler); - - // Monitor parent process - exit if parent (sshd) dies (ppid becomes 1) - pid_t originalPpid = getppid(); - dispatch_source_t parentTimer = dispatch_source_create( - DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); - dispatch_source_set_timer(parentTimer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0); - dispatch_source_set_event_handler(parentTimer, ^{ - if (getppid() != originalPpid) { - // Parent changed (likely died and we got reparented to launchd/init) - exit(0); - } - }); - dispatch_resume(parentTimer); - - // Boost main thread to real-time priority for better daemon performance - struct sched_param param; - param.sched_priority = sched_get_priority_max(SCHED_RR); - pthread_setschedparam(pthread_self(), SCHED_RR, ¶m); - CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)exitProcess, CFSTR(kPreferencesNotify), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); [ScreenDumpVNC load];