From 227f87d3392dcfd63af72233a95c8a0744ffacaf Mon Sep 17 00:00:00 2001 From: Igor Randjelovic Date: Fri, 30 Oct 2026 23:15:06 +0100 Subject: [PATCH] fix: make devicectl launches work with debug-brk and report the pid --start-stopped suspends the process without telling the runtime to wait for a debugger, so nothing resumes it. The app now gets --nativescript-debug-brk like the pre-iOS 17 path, and the runtime waits. App arguments have to come after devicectl's own options. The start response includes the pid, so the CLI can attach a native debugger. --- IOSDeviceLib/Constants.h | 1 + IOSDeviceLib/DevicectlHelper.cpp | 12 +++++++----- IOSDeviceLib/DevicectlHelper.h | 2 +- IOSDeviceLib/IOSDeviceLib.cpp | 4 +++- typings/interfaces.d.ts | 9 ++++++++- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/IOSDeviceLib/Constants.h b/IOSDeviceLib/Constants.h index 698300e..b7aacef 100644 --- a/IOSDeviceLib/Constants.h +++ b/IOSDeviceLib/Constants.h @@ -76,6 +76,7 @@ static const char *kCurrentApplicationsKey = "CurrentList"; static const char *kCommandKey = "Command"; static const char *kStatusKey = "Status"; static const char *kResponse = "response"; +static const char *kPid = "pid"; static const char *kSocket = "socket"; static const char *kMessage = "message"; static const char *kResponseCommandType = "responseCommandType"; diff --git a/IOSDeviceLib/DevicectlHelper.cpp b/IOSDeviceLib/DevicectlHelper.cpp index d5b625b..c698f25 100644 --- a/IOSDeviceLib/DevicectlHelper.cpp +++ b/IOSDeviceLib/DevicectlHelper.cpp @@ -8,11 +8,12 @@ using json = nlohmann::json; -json run_devicectl(std::string command){ +json run_devicectl(std::string command, std::string app_arguments = ""){ char templatea[] = "/tmp/mytempfile-XXXXXX"; char* tempFileDir = mkdtemp(templatea); std::string outputFile = std::string(tempFileDir) + "tempFileName"; - std::string commandWithJson = command + " --quiet --json-output "+outputFile; + // devicectl hands everything after "--" to the launched app. + std::string commandWithJson = command + " --quiet --json-output " + outputFile + (app_arguments.empty() ? "" : " -- " + app_arguments); std::string cmdResult = exec(commandWithJson.c_str()); FileInfo result = get_file_info(outputFile, true); std::remove(outputFile.c_str()); @@ -66,12 +67,13 @@ bool devicectl_stop_application(std::string &executable, std::string &device_ide } -bool devicectl_start_application(std::string &bundle_id, std::string &device_identifier, bool wait_for_debugger) { +bool devicectl_start_application(std::string &bundle_id, std::string &device_identifier, bool wait_for_debugger, int &pid) { - std::string command = "xcrun devicectl device process launch --device " + device_identifier + " --terminate-existing " + bundle_id + (wait_for_debugger?" --start-stopped":""); + std::string command = "xcrun devicectl device process launch --device " + device_identifier + " --terminate-existing " + bundle_id; - json result = run_devicectl(command); + json result = run_devicectl(command, wait_for_debugger ? "--nativescript-debug-brk" : ""); if(json_ok(result)){ + pid = result.value("result", json()).value("process", json()).value("processIdentifier", -1); return true; } return false; diff --git a/IOSDeviceLib/DevicectlHelper.h b/IOSDeviceLib/DevicectlHelper.h index b9ad160..bbb4ab0 100644 --- a/IOSDeviceLib/DevicectlHelper.h +++ b/IOSDeviceLib/DevicectlHelper.h @@ -2,4 +2,4 @@ #include "Declarations.h" bool devicectl_stop_application(std::string &executable, std::string &device_identifier); -bool devicectl_start_application(std::string &bundle_id, std::string &device_identifier, bool wait_for_debugger); +bool devicectl_start_application(std::string &bundle_id, std::string &device_identifier, bool wait_for_debugger, int &pid); diff --git a/IOSDeviceLib/IOSDeviceLib.cpp b/IOSDeviceLib/IOSDeviceLib.cpp index b3aa1eb..185149a 100644 --- a/IOSDeviceLib/IOSDeviceLib.cpp +++ b/IOSDeviceLib/IOSDeviceLib.cpp @@ -1748,8 +1748,10 @@ void start_app(std::string device_identifier, kApplicationsCustomError); } else { if(check_xcode_major_version(15, device_identifier, method_id)){ - if(devicectl_start_application(application_identifier, device_identifier, wait_for_debugger)) + int pid = -1; + if(devicectl_start_application(application_identifier, device_identifier, wait_for_debugger, pid)) print(json({{kResponse, "Successfully started application"}, + {kPid, pid}, {kId, method_id}, {kDeviceId, device_identifier}})); else diff --git a/typings/interfaces.d.ts b/typings/interfaces.d.ts index f1de45f..605c29d 100644 --- a/typings/interfaces.d.ts +++ b/typings/interfaces.d.ts @@ -75,6 +75,13 @@ declare global { response: string; } + interface IStartApplicationResponse extends IDeviceResponse { + /** + * Process id of the started application, on devices running iOS 17 or later. + */ + pid?: number; + } + interface IDeviceMultipleResponse extends IDeviceId { response: string[]; } @@ -179,7 +186,7 @@ declare global { postNotification(postNotificationArray: IPostNotificationData[]): Promise[]; awaitNotificationResponse(awaitNotificationResponseArray: IAwaitNotificatioNResponseData[]): Promise[]; apps(deviceIdentifiers: string[]): Promise[]; - start(startArray: IIOSApplicationData[]): Promise[]; + start(startArray: IIOSApplicationData[]): Promise[]; stop(stopArray: IIOSApplicationData[]): Promise[]; startDeviceLog(deviceIdentifiers: string[]): void; startDeviceLogStream(logStreamArray: IDeviceLogStreamData[]): void;