<commit_before>module RunLoop

  # A class for interacting with the instruments command-line tool
  #
  # @note All instruments commands are run in the context of `xcrun`.
  #
  # @todo Detect Instruments.app is running and pop an alert.
  class Instruments

    # Returns an Array of instruments process ids.
    #
    # @note The `block` parameter is included for legacy API and will be
    #  deprecated.  Replace your existing calls with with .each or .map.  The
    #  block argument makes this method hard to mock.
    # @return [Array<Integer>] An array of instruments process ids.
    def instruments_pids(&block)
      pids = pids_from_ps_output
      if block_given?
        pids.each do |pid|
          block.call(pid)
        end
      else
        pids
      end
    end

    # Are there any instruments processes running?
    # @return [Boolean] True if there is are any instruments processes running.
    def instruments_running?
      instruments_pids.count > 0
    end

    # Send a kill signal to any running `instruments` processes.
    #
    # Only one instruments process can be running at any one time.
    #
    # @param [RunLoop::XCTools] xcode_tools The Xcode tools to use to determine
    #  what version of Xcode is active.
    def kill_instruments(xcode_tools = RunLoop::XCTools.new)
      kill_signal = kill_signal xcode_tools
      # It is difficult to test using a block.
      instruments_pids.each do |pid|
        begin
          if ENV['DEBUG'] == '1'
            puts "Sending '#{kill_signal}' to instruments process '#{pid}'"
          end
          Process.kill(kill_signal, pid.to_i)
        rescue Exception => e
          if ENV['DEBUG'] == '1'
            puts "Could not kill process '#{pid.to_i}' - ignoring #{e}"
          end
        end

        # Process.wait or `wait` here is pointless.  The pid may or may not be
        # a child of this Process.
        begin
          if ENV['DEBUG'] == '1'
            puts "Waiting for instruments '#{pid}' to terminate"
          end
          wait_for_process_to_terminate(pid, {:timeout => 2.0})
        rescue Exception => e
          if ENV['DEBUG'] == '1'
            puts "Ignoring #{e.message}"
          end
        end
      end
    end

    private

    # @!visibility private
    # When run from calabash, expect this:
    #
    # ```
    # $ ps x -o pid,command | grep -v grep | grep instruments
    # 98081 sh -c xcrun instruments -w "43be3f89d9587e9468c24672777ff6241bd91124" < args >
    # 98082 /Xcode/6.0.1/Xcode.app/Contents/Developer/usr/bin/instruments -w < args >
    # ```<commit_msg>After killing instruments, try Process.wait<commit_after>module RunLoop

  # A class for interacting with the instruments command-line tool
  #
  # @note All instruments commands are run in the context of `xcrun`.
  #
  # @todo Detect Instruments.app is running and pop an alert.
  class Instruments

    # Returns an Array of instruments process ids.
    #
    # @note The `block` parameter is included for legacy API and will be
    #  deprecated.  Replace your existing calls with with .each or .map.  The
    #  block argument makes this method hard to mock.
    # @return [Array<Integer>] An array of instruments process ids.
    def instruments_pids(&block)
      pids = pids_from_ps_output
      if block_given?
        pids.each do |pid|
          block.call(pid)
        end
      else
        pids
      end
    end

    # Are there any instruments processes running?
    # @return [Boolean] True if there is are any instruments processes running.
    def instruments_running?
      instruments_pids.count > 0
    end

    # Send a kill signal to any running `instruments` processes.
    #
    # Only one instruments process can be running at any one time.
    #
    # @param [RunLoop::XCTools] xcode_tools The Xcode tools to use to determine
    #  what version of Xcode is active.
    def kill_instruments(xcode_tools = RunLoop::XCTools.new)
      kill_signal = kill_signal xcode_tools
      # It is difficult to test using a block.
      instruments_pids.each do |pid|
        begin
          if ENV['DEBUG'] == '1'
            puts "Sending '#{kill_signal}' to instruments process '#{pid}'"
          end
          Process.kill(kill_signal, pid.to_i)
          Process.wait(pid, Process::WNOHANG)
        rescue Exception => e
          if ENV['DEBUG'] == '1'
            puts "Could not kill process '#{pid.to_i}' - ignoring #{e}"
          end
        end

        # Process.wait or `wait` here is pointless.  The pid may or may not be
        # a child of this Process.
        begin
          if ENV['DEBUG'] == '1'
            puts "Waiting for instruments '#{pid}' to terminate"
          end
          wait_for_process_to_terminate(pid, {:timeout => 2.0})
        rescue Exception => e
          if ENV['DEBUG'] == '1'
            puts "Ignoring #{e.message}"
          end
        end
      end
    end

    private

    # @!visibility private
    # When run from calabash, expect this:
    #
    # ```
    # $ ps x -o pid,command | grep -v grep | grep instruments
    # 98081 sh -c xcrun instruments -w "43be3f89d9587e9468c24672777ff6241bd91124" < args >
    # 98082 /Xcode/6.0.1/Xcode.app/Contents/Developer/usr/bin/instruments -w < args >
    # ```
{'fraction_non_alphanumeric': 0.08652751423149906, 'fraction_numerical': 0.018975332068311195, 'mean_word_length': 2.20815581253804, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '895699', 'n_tokens_mistral': 1629, 'n_tokens_neox': 1554, 'n_words': 556}