process_starter 1.0.0

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/process_starter.rb +90 -0
  2. metadata +67 -0
@@ -0,0 +1,90 @@
1
+ # 2012 (c) LineAct / www.lineact.com
2
+
3
+ module ProcessStarter
4
+ begin require 'posix/spawn' rescue LoadError; end
5
+
6
+ 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
9
+
10
+ def log(m)
11
+ defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER.info(m) : puts m
12
+ end
13
+
14
+ # Starts the process
15
+ # not waiting for it's finish, so child process run in parralel
16
+ # not inheritting file descriptors, so it finds and closes all opened handels
17
+ # works in windows and linux
18
+ 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}"
20
+ 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)"
25
+ else
26
+ log.info "Execute failed!"
27
+ end
28
+ else
29
+ log.info "Executing in Linux style"
30
+ if HAVE_POSIX_SPAWN
31
+ 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)
34
+ elsif HAVE_SPAWN
35
+ # we hope on http://www.ruby-doc.org/core-1.9.3/Process.html#method-c-spawn
36
+ # [close_others => true] option
37
+ # TODO: check it
38
+ log.info "Ruby 1.9 spawn"
39
+ spawn( s )
40
+ else
41
+ log.info "fork{ close_io; exec }"
42
+ Process.detach fork{
43
+ close_io(true)
44
+ exec(s)
45
+ }
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+ # based on close_io from: http://daemons.rubyforge.org/Daemonize.html
52
+ def self.close_io( do_close=false )
53
+ close_them = []
54
+ # Make sure all input/output streams are closed
55
+ # Part I: close all IO objects (except for STDIN/STDOUT/STDERR)
56
+ ObjectSpace.each_object(IO) do |io|
57
+ unless [STDIN, STDOUT, STDERR].include?(io)
58
+ begin
59
+ # puts "os #{io.to_i}, and="
60
+ # puts io.fcntl(Fcntl::F_GETFD) & Fcntl::FD_CLOEXEC
61
+ if (not io.closed?) and (io.fcntl(Fcntl::F_GETFD) & Fcntl::FD_CLOEXEC) == 0
62
+ close_them << io.to_i
63
+ io.close if do_close
64
+ end
65
+ rescue ::Exception
66
+ end
67
+ end
68
+ end
69
+ # puts close_them.inspect
70
+
71
+ # Make sure all input/output streams are closed
72
+ # Part II: close all file decriptors (except for STDIN/STDOUT/STDERR)
73
+ ios = Array.new(8192) {|i| IO.for_fd(i) rescue nil}.compact
74
+ ios.each do |io|
75
+ # puts "qqq"
76
+ # puts io.to_i
77
+ 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)
81
+ # puts "adding"
82
+ close_them << io.to_i
83
+ io.close if do_close
84
+ end
85
+ # puts close_them.inspect
86
+
87
+ close_them.uniq
88
+ end
89
+
90
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: process_starter
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Pavel Vasev
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-09-21 00:00:00 +06:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: A gem to start process in parallel plus dont inherit handles plus both in windows/linux plus learn me to make gems
23
+ email: pavel.vasev@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/process_starter.rb
32
+ has_rdoc: true
33
+ homepage: http://rubygems.org/gems/process_starter
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options: []
38
+
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ hash: 3
47
+ segments:
48
+ - 0
49
+ version: "0"
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.5.2
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: Hola!
66
+ test_files: []
67
+