process_starter 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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