process_starter 1.0.0 → 1.0.1
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.
- data/Rakefile +8 -0
- data/lib/process_starter.rb +39 -27
- data/test/test2child.arb +10 -0
- data/test/test_process_starter.rb +47 -0
- metadata +8 -5
data/Rakefile
ADDED
data/lib/process_starter.rb
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
# 2012 (c) LineAct / www.lineact.com
|
2
2
|
|
3
|
+
require 'rubygems'
|
4
|
+
require 'fcntl'
|
5
|
+
|
6
|
+
# https://github.com/rtomayko/posix-spawn
|
7
|
+
begin; require( 'posix/spawn' ) ; rescue LoadError ; end
|
8
|
+
|
3
9
|
module ProcessStarter
|
4
|
-
begin require 'posix/spawn' rescue LoadError; end
|
5
10
|
|
6
11
|
WINRUN = (RUBY_PLATFORM =~ /mswin|mingw/) ? true : false # run in windows?
|
7
|
-
HAVE_SPAWN = defined?(spawn) # have Ruby 1.9 spawn method
|
8
|
-
HAVE_POSIX_SPAWN = defined?(POSIX::Spawn::spawn) # loaded posix/spawn lib
|
12
|
+
HAVE_SPAWN = defined?(spawn) ? true : false # have Ruby 1.9 spawn method
|
13
|
+
HAVE_POSIX_SPAWN = defined?(POSIX::Spawn::spawn) ? true : false # loaded posix/spawn lib
|
14
|
+
HAVE_PSEXEC = WINRUN ? ((`psexec /?` rescue "") =~ /computer/ ? true : false) : false
|
9
15
|
|
10
|
-
def log(m)
|
11
|
-
defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER.info(m) : puts
|
16
|
+
def self.log(m)
|
17
|
+
defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER.info(m) : puts(m)
|
12
18
|
end
|
13
19
|
|
14
20
|
# Starts the process
|
@@ -16,40 +22,39 @@ module ProcessStarter
|
|
16
22
|
# not inheritting file descriptors, so it finds and closes all opened handels
|
17
23
|
# works in windows and linux
|
18
24
|
def self.start(s)
|
19
|
-
log
|
25
|
+
log "**************** INVOKING EXTERNAL COMMAND #{s}, WINRUN IS #{WINRUN}, HAVE_PSEXEC IS #{HAVE_PSEXEC}, HAVE_POSIX_SPAWN IS #{HAVE_POSIX_SPAWN}, HAVE_SPAWN is #{HAVE_SPAWN}"
|
20
26
|
if WINRUN
|
21
|
-
if
|
22
|
-
log
|
23
|
-
|
24
|
-
log.info "Executed using START cmd /c (inherits descriptors (?) - bad)"
|
27
|
+
if HAVE_PSEXEC
|
28
|
+
log "starting using psexec"
|
29
|
+
r = system("psexec -d #{s}")
|
25
30
|
else
|
26
|
-
log
|
31
|
+
log "starting using START cmd /c (inherits descriptors (?) - bad)"
|
32
|
+
system("start cmd /c #{s}")
|
27
33
|
end
|
28
34
|
else
|
29
|
-
log
|
35
|
+
log "Executing in Linux style"
|
30
36
|
if HAVE_POSIX_SPAWN
|
31
37
|
close_them = Hash[ close_io().map {|x| [x, :close]} ]
|
32
|
-
log
|
33
|
-
|
38
|
+
log "POSIX::Spawn::spawn with close descriptors: #{close_them.inspect}"
|
39
|
+
Process.detach POSIX::Spawn::spawn( s, close_them)
|
34
40
|
elsif HAVE_SPAWN
|
35
41
|
# we hope on http://www.ruby-doc.org/core-1.9.3/Process.html#method-c-spawn
|
36
42
|
# [close_others => true] option
|
37
43
|
# TODO: check it
|
38
|
-
log
|
39
|
-
spawn( s )
|
44
|
+
log "Ruby 1.9 spawn"
|
45
|
+
Process.detach spawn( s )
|
40
46
|
else
|
41
|
-
log
|
42
|
-
Process.detach fork{
|
47
|
+
log "fork{ close_io; exec }"
|
48
|
+
Process.detach fork {
|
43
49
|
close_io(true)
|
44
50
|
exec(s)
|
45
|
-
}
|
51
|
+
}
|
46
52
|
end
|
47
|
-
|
48
53
|
end
|
49
54
|
end
|
50
55
|
|
51
56
|
# based on close_io from: http://daemons.rubyforge.org/Daemonize.html
|
52
|
-
def self.close_io( do_close=false )
|
57
|
+
def self.close_io( do_close=false, debug = false )
|
53
58
|
close_them = []
|
54
59
|
# Make sure all input/output streams are closed
|
55
60
|
# Part I: close all IO objects (except for STDIN/STDOUT/STDERR)
|
@@ -72,12 +77,15 @@ module ProcessStarter
|
|
72
77
|
# Part II: close all file decriptors (except for STDIN/STDOUT/STDERR)
|
73
78
|
ios = Array.new(8192) {|i| IO.for_fd(i) rescue nil}.compact
|
74
79
|
ios.each do |io|
|
75
|
-
|
76
|
-
|
80
|
+
puts "qqq" if debug
|
81
|
+
puts io.to_i if debug
|
77
82
|
next if io.fileno < 3
|
78
|
-
|
79
|
-
|
80
|
-
|
83
|
+
puts "checking flag" if debug
|
84
|
+
r = begin; io.fcntl(Fcntl::F_GETFD) & Fcntl::FD_CLOEXEC != 0 rescue false; end
|
85
|
+
puts r
|
86
|
+
# puts io.fcntl(Fcntl::F_GETFD) & Fcntl::FD_CLOEXEC
|
87
|
+
# next if (io.fcntl(Fcntl::F_GETFD) & Fcntl::FD_CLOEXEC != 0)
|
88
|
+
next if r
|
81
89
|
# puts "adding"
|
82
90
|
close_them << io.to_i
|
83
91
|
io.close if do_close
|
@@ -87,4 +95,8 @@ module ProcessStarter
|
|
87
95
|
close_them.uniq
|
88
96
|
end
|
89
97
|
|
90
|
-
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# f = File.open("test2.txt","w")
|
101
|
+
# d = ProcessStarter.close_io()
|
102
|
+
# puts "Parent descriptors: #{d.inspect}"
|
data/test/test2child.arb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
puts "im a child"
|
2
|
+
#require File.join( File.expand_path(File.dirname(__FILE__)), "..","lib","process_starter.rb" )
|
3
|
+
#d = ProcessStarter.close_io()
|
4
|
+
#puts "im a child and my descriptors: #{d.inspect}"
|
5
|
+
#puts "im a child and my descriptors:"
|
6
|
+
|
7
|
+
puts `ls -l /proc/#{Process.pid}/fd` rescue nil
|
8
|
+
`echo 123 >#{File.expand_path(File.dirname(__FILE__))}/chout2`
|
9
|
+
sleep ARGV[0].to_i rescue 0
|
10
|
+
puts "i am child and i finish"
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'process_starter'
|
3
|
+
|
4
|
+
class ProcessStarterTest < Test::Unit::TestCase
|
5
|
+
# def test_english_hello
|
6
|
+
# assert_equal "hello world",
|
7
|
+
# Hola.hi("english")
|
8
|
+
# end
|
9
|
+
|
10
|
+
# def test_visually_one
|
11
|
+
# puts "I am test_visually_one"
|
12
|
+
# end
|
13
|
+
|
14
|
+
def test_visually
|
15
|
+
puts "I am test_visually"
|
16
|
+
f = File.open("test2.txt","w")
|
17
|
+
puts "I opened test2.txt, it's fd=#{f.to_i}"
|
18
|
+
fb = File.open("test2b.txt","w" )
|
19
|
+
#fb.fcntl(Fcntl::F_SETFD,fb.fcntl(Fcntl::F_GETFD) | Fcntl::FD_CLOEXEC )
|
20
|
+
puts "I opened test2b.txt, it's fd=#{fb.to_i}"
|
21
|
+
|
22
|
+
require 'socket' # Sockets are in standard library
|
23
|
+
host = '0.0.0.0'
|
24
|
+
port = 2008
|
25
|
+
s = TCPServer.open( port )
|
26
|
+
puts "I opened socket on port 2006, it's fd=#{s.to_i}"
|
27
|
+
|
28
|
+
# d = ProcessStarter.close_io()
|
29
|
+
puts "I am parent, my descriptors:"
|
30
|
+
puts ProcessStarter::WINRUN ? "non avail" : `ls -l /proc/#{Process.pid}/fd`
|
31
|
+
|
32
|
+
# r = ProcessStarter.start("ruby test/test2child.arb 120 >test/chout 2>&1")
|
33
|
+
|
34
|
+
ProcessStarter.start("ruby test/test2child.arb 120")
|
35
|
+
#stat = Process::waitpid(r)
|
36
|
+
|
37
|
+
#puts "i started child, r=#{r}, status = #{stat.inspect}"
|
38
|
+
if ProcessStarter::WINRUN
|
39
|
+
puts "We are in Windows, so i just sleep for 2 minutes so you can check handles manually, for ex using ProcessExplorer"
|
40
|
+
sleep 120
|
41
|
+
else
|
42
|
+
sleep 5
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: process_starter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Pavel Vasev
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-09-
|
18
|
+
date: 2012-09-23 00:00:00 +06:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -29,6 +29,9 @@ extra_rdoc_files: []
|
|
29
29
|
|
30
30
|
files:
|
31
31
|
- lib/process_starter.rb
|
32
|
+
- Rakefile
|
33
|
+
- test/test_process_starter.rb
|
34
|
+
- test/test2child.arb
|
32
35
|
has_rdoc: true
|
33
36
|
homepage: http://rubygems.org/gems/process_starter
|
34
37
|
licenses: []
|
@@ -62,6 +65,6 @@ rubyforge_project:
|
|
62
65
|
rubygems_version: 1.5.2
|
63
66
|
signing_key:
|
64
67
|
specification_version: 3
|
65
|
-
summary:
|
68
|
+
summary: Process Starter / not inherit file descriptors
|
66
69
|
test_files: []
|
67
70
|
|