diff --git a/ios/instruments/processcontrol.go b/ios/instruments/processcontrol.go index d15790b5..eb115366 100644 --- a/ios/instruments/processcontrol.go +++ b/ios/instruments/processcontrol.go @@ -23,8 +23,8 @@ func (p *ProcessControl) LaunchApp(bundleID string, my_opts map[string]any) (uin } maps.Copy(opts, my_opts) // Xcode sends all these, no idea if we need them for sth. later. - //"CA_ASSERT_MAIN_THREAD_TRANSACTIONS": "0", "CA_DEBUG_TRANSACTIONS": "0", "LLVM_PROFILE_FILE": "/dev/null", "METAL_DEBUG_ERROR_MODE": "0", "METAL_DEVICE_WRAPPER_TYPE": "1", - //"OS_ACTIVITY_DT_MODE": "YES", "SQLITE_ENABLE_THREAD_ASSERTIONS": "1", "__XPC_LLVM_PROFILE_FILE": "/dev/null" + // "CA_ASSERT_MAIN_THREAD_TRANSACTIONS": "0", "CA_DEBUG_TRANSACTIONS": "0", "LLVM_PROFILE_FILE": "/dev/null", "METAL_DEBUG_ERROR_MODE": "0", "METAL_DEVICE_WRAPPER_TYPE": "1", + // "OS_ACTIVITY_DT_MODE": "YES", "SQLITE_ENABLE_THREAD_ASSERTIONS": "1", "__XPC_LLVM_PROFILE_FILE": "/dev/null" // NSUnbufferedIO seems to make the app send its logs via instruments using the outputReceived:fromProcess:atTime: selector // We'll supply per default to get logs env := map[string]interface{}{"NSUnbufferedIO": "YES"} @@ -40,8 +40,8 @@ func (p *ProcessControl) LaunchAppWithArgs(bundleID string, my_args []interface{ } maps.Copy(opts, my_opts) // Xcode sends all these, no idea if we need them for sth. later. - //"CA_ASSERT_MAIN_THREAD_TRANSACTIONS": "0", "CA_DEBUG_TRANSACTIONS": "0", "LLVM_PROFILE_FILE": "/dev/null", "METAL_DEBUG_ERROR_MODE": "0", "METAL_DEVICE_WRAPPER_TYPE": "1", - //"OS_ACTIVITY_DT_MODE": "YES", "SQLITE_ENABLE_THREAD_ASSERTIONS": "1", "__XPC_LLVM_PROFILE_FILE": "/dev/null" + // "CA_ASSERT_MAIN_THREAD_TRANSACTIONS": "0", "CA_DEBUG_TRANSACTIONS": "0", "LLVM_PROFILE_FILE": "/dev/null", "METAL_DEBUG_ERROR_MODE": "0", "METAL_DEVICE_WRAPPER_TYPE": "1", + // "OS_ACTIVITY_DT_MODE": "YES", "SQLITE_ENABLE_THREAD_ASSERTIONS": "1", "__XPC_LLVM_PROFILE_FILE": "/dev/null" // NSUnbufferedIO seems to make the app send its logs via instruments using the outputReceived:fromProcess:atTime: selector // We'll supply per default to get logs env := map[string]interface{}{"NSUnbufferedIO": "YES"} @@ -62,6 +62,18 @@ func NewProcessControl(device ios.DeviceEntry) (*ProcessControl, error) { return &ProcessControl{processControlChannel: processControlChannel, conn: dtxConn}, nil } +// DisableMemoryLimit disables the memory limit of a process. +func (p ProcessControl) DisableMemoryLimit(pid uint64) (bool, error) { + msg, err := p.processControlChannel.MethodCall("requestDisableMemoryLimitsForPid:", pid) + if err != nil { + return false, err + } + if disabled, ok := msg.Payload[0].(bool); ok { + return disabled, nil + } + return false, fmt.Errorf("expected int 0 or 1 as payload of msg: %v", msg) +} + // KillProcess kills the process on the device. func (p ProcessControl) KillProcess(pid uint64) error { _, err := p.processControlChannel.MethodCall("killPid:", pid) diff --git a/main.go b/main.go index 53a2a0f4..ee3b9138 100644 --- a/main.go +++ b/main.go @@ -112,6 +112,7 @@ Usage: ios apps [--system] [--all] [--list] [--filesharing] [options] ios launch [--wait] [--kill-existing] [--arg=]... [--env=]... [options] ios kill ( | --pid= | --process=) [options] + ios memlimitoff (--process=) [options] ios runtest [--bundle-id=] [--test-runner-bundle-id=] [--xctest-config=] [--log-output=] [--xctest] [--test-to-run=]... [--test-to-skip=]... [--env=]... [options] ios runwda [--bundleid=] [--testrunnerbundleid=] [--xctestconfig=] [--log-output=] [--arg=]... [--env=]... [options] ios ax [--font=] [options] @@ -226,6 +227,7 @@ The commands work as following: ios apps [--system] [--all] [--list] [--filesharing] Retrieves a list of installed applications. --system prints out preinstalled system apps. --all prints all apps, including system, user, and hidden apps. --list only prints bundle ID, bundle name and version number. --filesharing only prints apps which enable documents sharing. ios launch [--wait] [--kill-existing] [--arg=]... [--env=]... [options] Launch app with the bundleID on the device. Get your bundle ID from the apps command. --wait keeps the connection open if you want logs. ios kill ( | --pid= | --process=) [options] Kill app with the specified bundleID, process id, or process name on the device. + ios memlimitoff (--process=) [options] Waives memory limit set by iOS (For instance a Broadcast Extension limit is 50 MB). ios runtest [--bundle-id=] [--test-runner-bundle-id=] [--xctest-config=] [--log-output=] [--xctest] [--test-to-run=]... [--test-to-skip=]... [--env=]... [options] Run a XCUITest. If you provide only bundle-id go-ios will try to dynamically create test-runner-bundle-id and xctest-config. > If you provide '-' as log output, it prints resuts to stdout. > To be able to filter for tests to run or skip, use one argument per test selector. Example: runtest --test-to-run=(TestTarget.)TestClass/testMethod --test-to-run=(TestTarget.)TestClass/testMethod (the value for 'TestTarget' is optional) @@ -841,6 +843,28 @@ The commands work as following: printSysmontapStats(device) } + b, _ = arguments.Bool("memlimitoff") + if b { + processName, _ := arguments.String("--process") + + pControl, err := instruments.NewProcessControl(device) + exitIfError("processcontrol failed", err) + defer pControl.Close() + + svc, err := instruments.NewDeviceInfoService(device) + exitIfError("failed opening deviceInfoService for getting process list", err) + defer svc.Close() + + processList, _ := svc.ProcessList() + for _, process := range processList { + if process.Pid > 1 && process.Name == processName { + disabled, err := pControl.DisableMemoryLimit(process.Pid) + exitIfError("DisableMemoryLimit failed", err) + log.WithFields(log.Fields{"process": process.Name, "pid": process.Pid}).Info("memory limit is off: ", disabled) + } + } + } + b, _ = arguments.Bool("kill") if b { var response []installationproxy.AppInfo