frontkick 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/CHANGELOG.md +6 -0
- data/README.md +7 -11
- data/example/kill_child.rb +62 -36
- data/example/{spawn_opts.rb → popen3_options.rb} +0 -0
- data/example/{out_err.rb → redirect_without_shell.rb} +0 -0
- data/example/run.rb +2 -1
- data/lib/frontkick/result.rb +1 -1
- data/lib/frontkick/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6086b0058c21edf9586f841eef70e15a746dbbaf
|
4
|
+
data.tar.gz: 0b1f63ed60327e2907dee507eaebe8ac9393df06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 170164a43b0a1a5175418a6c0216034a6b9d2e43637595699289bc9d100ef85767f466ef1dd2803eac27cd1c42cdbc825037ba807bab7fe3ab02bd3b70d48c5f
|
7
|
+
data.tar.gz: 5631ed597d2e5134fc5ef914f2bf51275485635b9fe6f022e50a34c070fa88b6b7f4117bc0aa9fbd73eb90d68c0f5e2d7f768248a13ef0d6f222c0617ea578bf
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frontkick [](http://travis-ci.org/sonots/frontkick) [](https://gemnasium.com/sonots/frontkick)
|
2
2
|
|
3
|
-
testing ruby: 1.9.2, 1.9.3, 2.0.0;
|
4
|
-
|
5
3
|
Frontkick is a gem to execute a command and obtain exit\_code, stdout, stderr simply.
|
6
4
|
|
7
5
|
## What is This For?
|
@@ -72,35 +70,33 @@ Other options such as :chdir are treated as options of `Open3.#popen3`.
|
|
72
70
|
|
73
71
|
### Kill Child Process
|
74
72
|
|
75
|
-
|
73
|
+
Sending a signal to a kicked child process is fine because a frontkick process can finish.
|
74
|
+
But, sending a signal to a frontkick process is not fine because a child process would become an orphan process.
|
75
|
+
|
76
|
+
To kill your frontkick process with its child process correctly, send a signal to their **process group** as
|
76
77
|
|
77
78
|
kill -TERM -{PGID}
|
78
79
|
|
79
80
|
You can find PGID like `ps -eo pid,pgid,command`.
|
80
81
|
|
81
|
-
If you can not
|
82
|
+
If you can not take such an approach by some reasons (for example, `daemontools`, a process management tool,
|
83
|
+
does not support to send a signal to a process group), handle signal by yourself as
|
82
84
|
|
83
85
|
```ruby
|
84
86
|
Frontkick.exec(["sleep 100"]) do |wait_thr|
|
85
87
|
pid = wait_thr.pid
|
86
88
|
trap :INT do
|
87
89
|
Process.kill(:TERM, pid)
|
88
|
-
# wait child processes finish
|
89
|
-
begin
|
90
|
-
pid, status = Process.waitpid2(pid)
|
91
|
-
rescue Errno::ECHILD => e
|
92
|
-
end
|
93
90
|
exit 130
|
94
91
|
end
|
95
92
|
trap :TERM do
|
96
93
|
Process.kill(:TERM, pid)
|
97
|
-
Frontkick.process_wait(pid) # same with above
|
98
94
|
exit 143
|
99
95
|
end
|
100
96
|
end
|
101
97
|
```
|
102
98
|
|
103
|
-
More sophisticated example is available at [./example/kill_child.rb]
|
99
|
+
More sophisticated example is available at [./example/kill_child.rb](./example/kill_child.rb)
|
104
100
|
|
105
101
|
## Contributing
|
106
102
|
|
data/example/kill_child.rb
CHANGED
@@ -1,51 +1,77 @@
|
|
1
1
|
require 'frontkick'
|
2
2
|
|
3
|
-
|
3
|
+
class SignalHandler
|
4
|
+
def self.register
|
5
|
+
@pids ||= []
|
6
|
+
@main_threads ||= []
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
+
if @signal_pipe_r.nil? and @signal_pipe_w.nil?
|
9
|
+
@signal_pipe_r, @signal_pipe_w = IO.pipe
|
10
|
+
end
|
11
|
+
|
12
|
+
# For example, loogger `can't be called from trap context`
|
13
|
+
trap :INT do
|
14
|
+
@signal_pipe_w.puts 'INT'
|
15
|
+
end
|
16
|
+
trap :TERM do
|
17
|
+
@signal_pipe_w.puts 'TERM'
|
18
|
+
end
|
8
19
|
|
9
|
-
|
10
|
-
|
11
|
-
|
20
|
+
# Create a new thread to handle signals
|
21
|
+
# This example kills child (and self)
|
22
|
+
@signal_handler_thr ||= Thread.new do
|
23
|
+
begin
|
24
|
+
while readable_io = IO.select([@signal_pipe_r])
|
25
|
+
signal = readable_io.first[0].gets.strip
|
26
|
+
puts "#{signal} signal received"
|
27
|
+
@pids.each_with_index do |pid, idx|
|
28
|
+
main_thread = @main_threads[idx]
|
29
|
+
begin
|
30
|
+
puts "kill -#{signal} #{pid}"
|
31
|
+
Process.kill(signal, pid) rescue nil
|
32
|
+
rescue => e
|
33
|
+
main_thread.raise e
|
34
|
+
end
|
35
|
+
end
|
36
|
+
# case signal
|
37
|
+
# when 'INT'
|
38
|
+
# Kernel.exit(130)
|
39
|
+
# when 'TERM'
|
40
|
+
# Kernel.exit(148)
|
41
|
+
# end
|
42
|
+
end
|
43
|
+
rescue Exception => e
|
44
|
+
Thread.main.raise e
|
45
|
+
end
|
46
|
+
end
|
12
47
|
end
|
13
|
-
|
14
|
-
|
48
|
+
|
49
|
+
def self.push(pid)
|
50
|
+
@pids << pid
|
51
|
+
@main_threads << Thread.current
|
15
52
|
end
|
16
53
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
readable_io = IO.select([signal_pipe_r])
|
21
|
-
signal = readable_io.first[0].gets.strip
|
22
|
-
case signal
|
23
|
-
when 'INT'
|
24
|
-
puts "kill -INT #{pid}"
|
25
|
-
Process.kill('INT', pid) rescue nil
|
26
|
-
pid, status = Process.waitpid2(pid) rescue nil
|
27
|
-
Kernel.exit(130)
|
28
|
-
when 'TERM'
|
29
|
-
puts "kill -TERM #{pid}"
|
30
|
-
Process.kill('TERM', pid) rescue nil
|
31
|
-
pid, status = Process.waitpid2(pid) rescue nil
|
32
|
-
Kernel.exit(148)
|
33
|
-
end
|
54
|
+
def self.pop(pid)
|
55
|
+
@pids -= [pid]
|
56
|
+
@main_threads -= [Thread.current]
|
34
57
|
end
|
58
|
+
end
|
35
59
|
|
36
|
-
|
37
|
-
# Wait child to finish (for normal situation)
|
38
|
-
wait_thr.join
|
60
|
+
SignalHandler.register
|
39
61
|
|
40
|
-
|
41
|
-
|
42
|
-
|
62
|
+
puts "## Frontkick started"
|
63
|
+
puts "kill -TERM #{Process.pid} or Hit Ctrl-C in 10 seconds"
|
64
|
+
result = Frontkick.exec(["sleep 10"]) do |wait_thr|
|
65
|
+
begin
|
66
|
+
SignalHandler.push(wait_thr.pid)
|
67
|
+
puts wait_thr.value # wait child to finish (for normal situation)
|
43
68
|
ensure
|
44
|
-
|
45
|
-
signal_pipe_w.close rescue nil
|
69
|
+
SignalHandler.pop(wait_thr.pid)
|
46
70
|
end
|
47
71
|
end
|
48
72
|
|
49
|
-
|
50
|
-
|
73
|
+
puts "## Fronkick finished"
|
74
|
+
puts "kill -TERM #{Process.pid} or Hit Ctrl-C in 5 seconds"
|
75
|
+
sleep 5
|
76
|
+
|
51
77
|
puts result.inspect
|
File without changes
|
File without changes
|
data/example/run.rb
CHANGED
data/lib/frontkick/result.rb
CHANGED
@@ -9,7 +9,7 @@ module Frontkick
|
|
9
9
|
def initialize(params = {})
|
10
10
|
@stdout = params[:stdout] || ""
|
11
11
|
@stderr = params[:stderr] || ""
|
12
|
-
@exit_code = params[:exit_code]
|
12
|
+
@exit_code = params[:exit_code] # exit_code would be nil if child process is killed -9
|
13
13
|
@duration = params[:duration] || 0
|
14
14
|
end
|
15
15
|
|
data/lib/frontkick/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: frontkick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Naotoshi Seo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -69,9 +69,9 @@ files:
|
|
69
69
|
- Rakefile
|
70
70
|
- example/dry_run.rb
|
71
71
|
- example/kill_child.rb
|
72
|
-
- example/
|
72
|
+
- example/popen3_options.rb
|
73
|
+
- example/redirect_without_shell.rb
|
73
74
|
- example/run.rb
|
74
|
-
- example/spawn_opts.rb
|
75
75
|
- experiment/capture3_no_deadlock.rb
|
76
76
|
- experiment/cat_63k.rb
|
77
77
|
- experiment/cat_64k.rb
|