Use launchctl
to get running processes by bundle ID.
This commit is contained in:
parent
88d0e8c2e6
commit
86a80c8a3d
@ -1,4 +1,5 @@
|
|||||||
require "pathname"
|
require "pathname"
|
||||||
|
require "timeout"
|
||||||
|
|
||||||
require "hbc/artifact/base"
|
require "hbc/artifact/base"
|
||||||
|
|
||||||
@ -127,10 +128,18 @@ module Hbc
|
|||||||
def uninstall_quit(directives)
|
def uninstall_quit(directives)
|
||||||
Array(directives[:quit]).each do |id|
|
Array(directives[:quit]).each do |id|
|
||||||
ohai "Quitting application ID #{id}"
|
ohai "Quitting application ID #{id}"
|
||||||
num_running = count_running_processes(id)
|
next if running_processes(id).empty?
|
||||||
next unless num_running > 0
|
|
||||||
@command.run!("/usr/bin/osascript", args: ["-e", %Q(tell application id "#{id}" to quit)], sudo: true)
|
@command.run!("/usr/bin/osascript", args: ["-e", %Q(tell application id "#{id}" to quit)], sudo: true)
|
||||||
sleep 3
|
|
||||||
|
begin
|
||||||
|
Timeout.timeout(3) do
|
||||||
|
Kernel.loop do
|
||||||
|
break if running_processes(id).empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue Timeout::Error
|
||||||
|
next
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -138,9 +147,9 @@ module Hbc
|
|||||||
def uninstall_signal(directives)
|
def uninstall_signal(directives)
|
||||||
Array(directives[:signal]).flatten.each_slice(2) do |pair|
|
Array(directives[:signal]).flatten.each_slice(2) do |pair|
|
||||||
raise CaskInvalidError.new(@cask, "Each #{stanza} :signal must have 2 elements.") unless pair.length == 2
|
raise CaskInvalidError.new(@cask, "Each #{stanza} :signal must have 2 elements.") unless pair.length == 2
|
||||||
signal, id = pair
|
signal, bundle_id = pair
|
||||||
ohai "Signalling '#{signal}' to application ID '#{id}'"
|
ohai "Signalling '#{signal}' to application ID '#{bundle_id}'"
|
||||||
pids = get_unix_pids(id)
|
pids = running_processes(bundle_id).map(&:first)
|
||||||
next unless pids.any?
|
next unless pids.any?
|
||||||
# Note that unlike :quit, signals are sent from the current user (not
|
# Note that unlike :quit, signals are sent from the current user (not
|
||||||
# upgraded to the superuser). This is a todo item for the future, but
|
# upgraded to the superuser). This is a todo item for the future, but
|
||||||
@ -148,24 +157,20 @@ module Hbc
|
|||||||
# misapplied "kill" by root could bring down the system. The fact that we
|
# misapplied "kill" by root could bring down the system. The fact that we
|
||||||
# learned the pid from AppleScript is already some degree of protection,
|
# learned the pid from AppleScript is already some degree of protection,
|
||||||
# though indirect.
|
# though indirect.
|
||||||
odebug "Unix ids are #{pids.inspect} for processes with bundle identifier #{id}"
|
odebug "Unix ids are #{pids.inspect} for processes with bundle identifier #{bundle_id}"
|
||||||
Process.kill(signal, *pids)
|
Process.kill(signal, *pids)
|
||||||
sleep 3
|
sleep 3
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def count_running_processes(bundle_id)
|
def running_processes(bundle_id)
|
||||||
@command.run!("/usr/bin/osascript",
|
@command.run!("/bin/launchctl", args: ["list"]).stdout.lines
|
||||||
args: ["-e", %Q(tell application "System Events" to count processes whose bundle identifier is "#{bundle_id}")],
|
.map { |line| line.chomp.split("\t") }
|
||||||
sudo: true).stdout.to_i
|
.map { |pid, state, id| [pid.to_i, state.to_i, id] }
|
||||||
end
|
.select do |fields|
|
||||||
|
next if fields[0].zero?
|
||||||
def get_unix_pids(bundle_id)
|
fields[2] =~ /^#{Regexp.escape(bundle_id)}($|\.\d+)/
|
||||||
pid_string = @command.run!("/usr/bin/osascript",
|
end
|
||||||
args: ["-e", %Q(tell application "System Events" to get the unix id of every process whose bundle identifier is "#{bundle_id}")],
|
|
||||||
sudo: true).stdout.chomp
|
|
||||||
return [] unless pid_string =~ /\A\d+(?:\s*,\s*\d+)*\Z/ # sanity check
|
|
||||||
pid_string.split(/\s*,\s*/).map(&:strip).map(&:to_i)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_login_item(directives)
|
def uninstall_login_item(directives)
|
||||||
|
@ -207,21 +207,17 @@ describe Hbc::Artifact::Uninstall do
|
|||||||
describe "when using quit" do
|
describe "when using quit" do
|
||||||
let(:cask) { Hbc.load("with-uninstall-quit") }
|
let(:cask) { Hbc.load("with-uninstall-quit") }
|
||||||
let(:bundle_id) { "my.fancy.package.app" }
|
let(:bundle_id) { "my.fancy.package.app" }
|
||||||
let(:count_processes_script) {
|
|
||||||
'tell application "System Events" to count processes ' +
|
|
||||||
%Q(whose bundle identifier is "#{bundle_id}")
|
|
||||||
}
|
|
||||||
let(:quit_application_script) {
|
let(:quit_application_script) {
|
||||||
%Q(tell application id "#{bundle_id}" to quit)
|
%Q(tell application id "#{bundle_id}" to quit)
|
||||||
}
|
}
|
||||||
|
|
||||||
it "can uninstall" do
|
it "can uninstall" do
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
sudo(%W[/usr/bin/osascript -e #{count_processes_script}]), "1"
|
%w[/bin/launchctl list], "999\t0\t#{bundle_id}\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
sudo(%W[/usr/bin/osascript -e #{quit_application_script}])
|
%w[/bin/launchctl list]
|
||||||
)
|
)
|
||||||
|
|
||||||
subject
|
subject
|
||||||
@ -233,14 +229,10 @@ describe Hbc::Artifact::Uninstall do
|
|||||||
let(:bundle_id) { "my.fancy.package.app" }
|
let(:bundle_id) { "my.fancy.package.app" }
|
||||||
let(:signals) { %w[TERM KILL] }
|
let(:signals) { %w[TERM KILL] }
|
||||||
let(:unix_pids) { [12_345, 67_890] }
|
let(:unix_pids) { [12_345, 67_890] }
|
||||||
let(:get_unix_pids_script) {
|
|
||||||
'tell application "System Events" to get the unix id of every process ' +
|
|
||||||
%Q(whose bundle identifier is "#{bundle_id}")
|
|
||||||
}
|
|
||||||
|
|
||||||
it "can uninstall" do
|
it "can uninstall" do
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
sudo(%W[/usr/bin/osascript -e #{get_unix_pids_script}]), unix_pids.join(", ")
|
%w[/bin/launchctl list], unix_pids.map { |pid| [pid, 0, bundle_id].join("\t") }.join("\n")
|
||||||
)
|
)
|
||||||
|
|
||||||
signals.each do |signal|
|
signals.each do |signal|
|
||||||
|
@ -208,21 +208,17 @@ describe Hbc::Artifact::Zap do
|
|||||||
describe "when using quit" do
|
describe "when using quit" do
|
||||||
let(:cask) { Hbc.load("with-zap-quit") }
|
let(:cask) { Hbc.load("with-zap-quit") }
|
||||||
let(:bundle_id) { "my.fancy.package.app" }
|
let(:bundle_id) { "my.fancy.package.app" }
|
||||||
let(:count_processes_script) {
|
|
||||||
'tell application "System Events" to count processes ' +
|
|
||||||
%Q(whose bundle identifier is "#{bundle_id}")
|
|
||||||
}
|
|
||||||
let(:quit_application_script) {
|
let(:quit_application_script) {
|
||||||
%Q(tell application id "#{bundle_id}" to quit)
|
%Q(tell application id "#{bundle_id}" to quit)
|
||||||
}
|
}
|
||||||
|
|
||||||
it "can zap" do
|
it "can zap" do
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
sudo(%W[/usr/bin/osascript -e #{count_processes_script}]), "1"
|
%w[/bin/launchctl list], "999\t0\t#{bundle_id}\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
sudo(%W[/usr/bin/osascript -e #{quit_application_script}])
|
%w[/bin/launchctl list]
|
||||||
)
|
)
|
||||||
|
|
||||||
subject
|
subject
|
||||||
@ -234,14 +230,10 @@ describe Hbc::Artifact::Zap do
|
|||||||
let(:bundle_id) { "my.fancy.package.app" }
|
let(:bundle_id) { "my.fancy.package.app" }
|
||||||
let(:signals) { %w[TERM KILL] }
|
let(:signals) { %w[TERM KILL] }
|
||||||
let(:unix_pids) { [12_345, 67_890] }
|
let(:unix_pids) { [12_345, 67_890] }
|
||||||
let(:get_unix_pids_script) {
|
|
||||||
'tell application "System Events" to get the unix id of every process ' +
|
|
||||||
%Q(whose bundle identifier is "#{bundle_id}")
|
|
||||||
}
|
|
||||||
|
|
||||||
it "can zap" do
|
it "can zap" do
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
sudo(%W[/usr/bin/osascript -e #{get_unix_pids_script}]), unix_pids.join(", ")
|
%w[/bin/launchctl list], unix_pids.map { |pid| [pid, 0, bundle_id].join("\t") }.join("\n")
|
||||||
)
|
)
|
||||||
|
|
||||||
signals.each do |signal|
|
signals.each do |signal|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user