ios-control / ios-deploy

Install and debug iPhone apps from the command line, without using Xcode
GNU General Public License v3.0
3.33k stars 462 forks source link

Python multithreading ios-deploy with subprocess hangs #589

Open SachaTe opened 10 months ago

SachaTe commented 10 months ago

Command Executed

Running the following via python threads;

ios-deploy --id --bundle --noinstall --bundle_id --noninteractive --args --version

Expected behavior

Print the device version and return for all devices.

Actual behavior.

Prints the device version and freezes, although the app has terminated and I see the PROCESS_EXITED bring printed, as follows;

     (lldb)     connect
     (lldb)     run
     success
     (lldb)     autoexit
    1.0.12

     PROCESS_EXITED

This issue does not occur when running multiple ios-deploy instances in parallel via bash. However it occurs when running via multi-threads on python.

Out of all the devices running on in parallel, it only passes for the last device to be executed. For example if I execute 5 threads for 5 different iphones, only the 5th thread will return.

This code used to run properly as we have been using it for over a year. Only recently (a few weeks ago) it broke. Seems to be broken on multiple macbooks.

Steps to reproduce the problem

import concurrent.futures
import subprocess

APP_LOCATION = "APP_LOCATION"
BUNDLE_ID = "BUNDLE_PATH"

def run_quiet(args, id):
    print(f"========= Starting {id} =========")
    print(" ".join(args))

    result = subprocess.run(
        args,
        universal_newlines=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
    )

    print(result.stdout)

    print(f"========= COMPLETED {id} =========")

def thread(id):
    version_cmd = [
        "ios-deploy",
        "--id",
        f"{id}",
        "--bundle",
        APP_LOCATION,
        "--noinstall",
        "--bundle_id",
        BUNDLE_ID,
        "--noninteractive",
        "--args",
        "--version",
    ]
    run_quiet(version_cmd, id)

list = [
    "REDACTED-ID-1",
    "REDACTED-ID-2",
]

with concurrent.futures.ThreadPoolExecutor() as executor:
    futures = [executor.submit(thread, id) for id in list]

concurrent.futures.wait(futures)

System Specs

This occurs on multiple devices

  1. system_profiler SPSoftwareDataType

    Software:
    
    System Software Overview:
    
      System Version: macOS 13.5 (22G74)
      Kernel Version: Darwin 22.6.0
      Boot Volume: Macintosh HD
      Boot Mode: Normal
      Computer Name: <REMOVED>
      User Name: <REMOVED>
      Secure Virtual Memory: Enabled
      System Integrity Protection: Enabled
      Time since boot: 16 hours, 45 minutes
  2. ios-deploy -V

    1.12.2
  3. xcodebuild -version (please note, attempted this with XCode 14.3 as well)

    Xcode 15.0
    Build version 15A5209g
  4. xcode-select --print-path

    /Applications/Xcode.app/Contents/Developer
  5. gcc --version

    Apple clang version 15.0.0 (clang-1500.0.38.1)
    Target: arm64-apple-darwin22.6.0
    Thread model: posix
    InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
  6. lldb --version

    lldb-1500.0.20.2
    Apple Swift version 5.9 (swiftlang-5.9.0.124.4 clang-1500.0.38.1)
gabebear commented 9 months ago

Is there a reason you need multiple threads?

The python interpreter is just the one shipped as part of LLDB along with Xcode. I'm not sure it supports multithreading(it's not easy to search since SOOO much of the documentation is about how to debug specific threads). The main documentation is at https://lldb.llvm.org/use/python-reference.html and running Python through LLDB on an iPhone should be the same as running Python via LLDB on your local computer.