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 ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
@@ -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 m
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.info "**************** INVOKING EXTERNAL COMMAND #{s}, WINRUN IS #{WINRUN}, HAVE_POSIX_SPAWN IS #{HAVE_POSIX_SPAWN}, HAVE_SPAWN is #{HAVE_SPAWN}"
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 system("psexec -d #{s}")
22
- log.info "Executed using PSEXEC"
23
- elsif system("start cmd /c #{s}")
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.info "Execute failed!"
31
+ log "starting using START cmd /c (inherits descriptors (?) - bad)"
32
+ system("start cmd /c #{s}")
27
33
  end
28
34
  else
29
- log.info "Executing in Linux style"
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.info "POSIX::Spawn::spawn with close descriptors: #{close_them.inspect}"
33
- pid = POSIX::Spawn::spawn( s, close_them)
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.info "Ruby 1.9 spawn"
39
- spawn( s )
44
+ log "Ruby 1.9 spawn"
45
+ Process.detach spawn( s )
40
46
  else
41
- log.info "fork{ close_io; exec }"
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
- # puts "qqq"
76
- # puts io.to_i
80
+ puts "qqq" if debug
81
+ puts io.to_i if debug
77
82
  next if io.fileno < 3
78
- # puts "checking flag"
79
- # puts io.fcntl(Fcntl::F_GETFD) & Fcntl::FD_CLOEXEC
80
- next if (io.fcntl(Fcntl::F_GETFD) & Fcntl::FD_CLOEXEC != 0)
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}"
@@ -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: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 0
10
- version: 1.0.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-21 00:00:00 +06:00
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: Hola!
68
+ summary: Process Starter / not inherit file descriptors
66
69
  test_files: []
67
70