frontkick 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://secure.travis-ci.org/sonots/frontkick.png?branch=master)](http://travis-ci.org/sonots/frontkick) [![Dependency Status](https://gemnasium.com/sonots/frontkick.png)](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
|