childlabor 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/child_labor.rb +151 -2
  2. metadata +4 -4
data/lib/child_labor.rb CHANGED
@@ -1,3 +1,152 @@
1
1
  module ChildLabor
2
- # Nothing here yet
3
- end
2
+ VERSION = '0.0.2'
3
+
4
+ def self.subprocess(cmd)
5
+ t = Task.new(cmd)
6
+ t.launch
7
+
8
+ if block_given?
9
+ begin
10
+ yield t
11
+ ensure
12
+ t.wait
13
+ t.close
14
+ end
15
+ end
16
+
17
+ return t
18
+ end
19
+
20
+ class Task
21
+ attr_reader :cmd
22
+
23
+ def initialize(cmd)
24
+ @cmd = cmd
25
+ @pid = nil
26
+ @exit_status = nil
27
+ @terminated = false
28
+ end
29
+
30
+ def launch
31
+ create_pipes
32
+
33
+ @pid = Process.fork
34
+
35
+ # child
36
+ unless @pid
37
+ @stdout.close
38
+ STDOUT.reopen @stdout_child
39
+
40
+ @stdin.close
41
+ STDIN.reopen @stdin_child
42
+
43
+ @stderr.close
44
+ STDERR.reopen @stderr_child
45
+
46
+ Process.exec cmd
47
+ end
48
+
49
+ @stdout_child.close
50
+ @stdin_child.close
51
+ @stderr_child.close
52
+
53
+ true
54
+ end
55
+
56
+ def launched?
57
+ @pid
58
+ end
59
+
60
+ def running?
61
+ poll_status(Process::WNOHANG)
62
+ end
63
+
64
+ def terminated?
65
+ !running?
66
+ end
67
+
68
+ def exit_status
69
+ poll_status
70
+ @exit_status
71
+ end
72
+
73
+ def wait
74
+ exit_status
75
+ end
76
+
77
+ def suspend
78
+ signal('STOP')
79
+ end
80
+
81
+ def resume
82
+ signal('CONT')
83
+ end
84
+
85
+ def terminate(signal = 'TERM')
86
+ signal(signal)
87
+ end
88
+
89
+ def read(length = nil, buffer = nil)
90
+ @stdout.read(length, buffer)
91
+ end
92
+
93
+ def read_stderr(length = nil, buffer = nil)
94
+ @stderr.read(length, buffer)
95
+ end
96
+
97
+ def write(str)
98
+ @stdin.write(str)
99
+ end
100
+
101
+ def signal(signal)
102
+ Process.kill(signal, @pid)
103
+ end
104
+
105
+ def close_read
106
+ @stdout.close if @stdout
107
+ @stdout = nil
108
+ end
109
+
110
+ def close_write
111
+ @stdin.close if @stdin
112
+ @stdin = nil
113
+ end
114
+
115
+ def close_stderr
116
+ @stderr.close if @stderr
117
+ @stderr = nil
118
+ end
119
+
120
+ def close
121
+ close_read
122
+ close_write
123
+ close_stderr
124
+ end
125
+
126
+ private
127
+
128
+ # Handles the state of the Task in a single call to
129
+ # Process.wait2.
130
+ # Returns true if the process is currently running
131
+ def poll_status(flags = 0)
132
+ return false unless @pid
133
+ return false if @terminated
134
+
135
+ pid, status = Process.wait2(@pid, flags)
136
+
137
+ return true unless pid
138
+
139
+ @terminated = true
140
+ @exit_status = status
141
+ false
142
+ rescue Errno::ECHILD
143
+ false
144
+ end
145
+
146
+ def create_pipes
147
+ @stdout, @stdout_child = IO.pipe
148
+ @stdin_child, @stdin = IO.pipe
149
+ @stderr, @stderr_child = IO.pipe
150
+ end
151
+ end
152
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: childlabor
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Carl Lerche
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-25 00:00:00 -07:00
18
+ date: 2010-06-28 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency