win32-process 0.5.8 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,6 @@
1
+ = 0.5.9 - 14-Jun-2008
2
+ * Added a proper implementation of Process.ppid.
3
+
1
4
  = 0.5.8 - 24-Mar-2008
2
5
  * Fixed a bug in Process.create where the handles in the PROCESS_INFORMATION
3
6
  struct were not closed, regardless of the 'close_handles' option. Thanks
data/README CHANGED
@@ -1,12 +1,12 @@
1
1
  = Description
2
2
  This package provides the fork, wait, wait2, waitpid, and waitpid2 methods
3
- for MS Windows. In addition, it provides a different implementation of the
4
- kill method.
3
+ for MS Windows. In addition, it provides a different implementation of the
4
+ kill method, and a proper implementation of the Process.ppid method.
5
5
 
6
6
  = Prerequisites
7
7
  Ruby 1.8.2 or later.
8
- The 'windows-pr' library, 0.7.4 or later.
9
- The 'sys-proctable' library, 0.7.0 or later (test suite only).
8
+ The 'windows-pr' library, 0.8.6 or later.
9
+ The 'sys-proctable' library, 0.7.6 or later (test suite only).
10
10
 
11
11
  = Supported Platforms
12
12
  This library is supported on Windows 2000 or later.
@@ -29,7 +29,7 @@
29
29
  puts 'Done'
30
30
 
31
31
  = Developer's Notes
32
- == The fork and wait methods
32
+ == The Process.fork and Process.wait methods
33
33
  The fork method is emulated on Windows by spawning another Ruby process
34
34
  against $PROGRAM_NAME via the CreateProcess() Win32 API function. It will
35
35
  use its parent's environment and starting directory.
@@ -46,25 +46,29 @@
46
46
  IMPORTANT!
47
47
  Note that because fork is calling CreateProcess($PROGRAM_NAME), it will
48
48
  start again from the top of the script instead of from the point of the
49
- call. We will try to address this in a future release, if possible.
49
+ call. We will try to address this in a future release, if possible.
50
50
 
51
- == The kill method
51
+ == The Process.kill method
52
52
  Initially, the kill method will try to get a HANDLE on the PID using the
53
- OpenProcess() function. If that succeeds, we know the process is running.
53
+ OpenProcess() function. If that succeeds, we know the process is running.
54
54
 
55
55
  In the event of signal 2 or signal 3, the GenerateConsoleCtrlEvent()
56
- function is used to send a signal to that process. These will not kill
57
- GUI processes. It will not (currently) send a signal to remote
56
+ function is used to send a signal to that process. These will not kill
57
+ GUI processes. It will not (currently) send a signal to remote
58
58
  processes.
59
59
 
60
60
  In the event of signal 1 or 4-8, the CreateRemoteThread() function is used
61
61
  after the HANDLE's process has been identified to create a thread
62
- within that process. The ExitProcess() function is then sent to that
62
+ within that process. The ExitProcess() function is then sent to that
63
63
  thread.
64
64
 
65
- In the event of signal 9, the TerminateProcess() function is called. This
65
+ In the event of signal 9, the TerminateProcess() function is called. This
66
66
  will almost certainly kill the process, but doesn't give the process a
67
67
  chance to necessarily do any cleanup it might otherwise do.
68
+
69
+ == The Process.ppid method
70
+ In MRI the Process.ppid always returns 0 on MS Windows. With this library
71
+ it returns the actual parent pid.
68
72
 
69
73
  == Differences between Ruby's kill and the Win32 Utils kill
70
74
  Ruby does not currently use the CreateRemoteThread() + ExitProcess()
data/lib/win32/process.rb CHANGED
@@ -7,14 +7,15 @@ require 'windows/library'
7
7
  require 'windows/console'
8
8
  require 'windows/window'
9
9
  require 'windows/unicode'
10
+ require 'windows/tool_helper'
10
11
 
11
12
  module Process
12
13
  class Error < RuntimeError; end
13
14
 
14
15
  # Eliminates redefinition warnings.
15
- undef_method :kill, :wait, :wait2, :waitpid, :waitpid2
16
+ undef_method :kill, :wait, :wait2, :waitpid, :waitpid2, :ppid
16
17
 
17
- WIN32_PROCESS_VERSION = '0.5.8'
18
+ WIN32_PROCESS_VERSION = '0.5.9'
18
19
 
19
20
  include Windows::Process
20
21
  include Windows::Thread
@@ -25,6 +26,7 @@ module Process
25
26
  include Windows::Synchronize
26
27
  include Windows::Window
27
28
  include Windows::Unicode
29
+ include Windows::ToolHelper
28
30
  extend Windows::Error
29
31
  extend Windows::Process
30
32
  extend Windows::Thread
@@ -33,6 +35,7 @@ module Process
33
35
  extend Windows::Library
34
36
  extend Windows::Console
35
37
  extend Windows::Unicode
38
+ extend Windows::ToolHelper
36
39
 
37
40
  # Used by Process.create
38
41
  ProcessInfo = Struct.new("ProcessInfo",
@@ -589,9 +592,46 @@ module Process
589
592
  nil
590
593
  end
591
594
 
595
+ # Returns the process ID of the parent of this process.
596
+ #--
597
+ # In MRI this method always returns 0.
598
+ #
599
+ def ppid
600
+ ppid = 0
601
+
602
+ return ppid if Process.pid == 0 # Paranoia
603
+
604
+ handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
605
+
606
+ if handle == INVALID_HANDLE_VALUE
607
+ raise Error, get_last_error
608
+ end
609
+
610
+ proc_entry = 0.chr * 296 # 36 + 260
611
+ proc_entry[0, 4] = [proc_entry.size].pack('L') # Set dwSize member
612
+
613
+ unless Process32First(handle, proc_entry)
614
+ CloseHandle(handle)
615
+ raise Error, get_last_error
616
+ end
617
+
618
+ while Process32Next(handle, proc_entry)
619
+ if proc_entry[8, 4].unpack('L')[0] == Process.pid
620
+ ppid = proc_entry[24, 4].unpack('L')[0] # th32ParentProcessID
621
+ break
622
+ end
623
+ end
624
+
625
+ ppid
626
+ end
627
+
592
628
  # Creates the equivalent of a subshell via the CreateProcess() function.
593
629
  # This behaves in a manner that is similar, but not identical to, the
594
- # Kernel.fork method for Unix.
630
+ # Kernel.fork method for Unix. Unlike the Unix fork, this method starts
631
+ # from the top of the script rather than the point of the call.
632
+ #
633
+ # WARNING: This implementation should be considered experimental. It is
634
+ # not recommended for production use.
595
635
  #
596
636
  def fork
597
637
  last_arg = ARGV.last
@@ -640,6 +680,7 @@ module Process
640
680
  end
641
681
 
642
682
  module_function :kill, :wait, :wait2, :waitpid, :waitpid2, :create, :fork
683
+ module_function :ppid
643
684
  end
644
685
 
645
686
  # For backwards compatibility. Deprecated.
data/test/tc_process.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  ###############################################################################
2
2
  # tc_process.rb
3
3
  #
4
- # Test suite for the win32-process package. This test suite will start
4
+ # Test suite for the win32-process library. This test suite will start
5
5
  # at least two instances of Notepad on your system, which will then
6
6
  # be killed. Requires the sys-proctable package.
7
7
  #
8
8
  # I haven't added a lot of test cases for fork/wait because it's difficult
9
- # to run such tests without causing havoc with TestUnit itself. Ideas
9
+ # to run such tests without causing havoc with Test::Unit itself. Ideas
10
10
  # welcome.
11
11
  #
12
12
  # You should run this test case via the 'rake test' task.
@@ -18,9 +18,12 @@ begin
18
18
  require 'sys/proctable'
19
19
  rescue LoadError => e
20
20
  site = 'http://www.rubyforge.org/projects/sysutils'
21
- STDERR.puts "Stopping!"
22
- STDERR.puts "The sys/proctable module is required to run this test suite."
23
- STDERR.puts "You can find it at #{site} or the RAA"
21
+ msg = %Q{
22
+ Stopping! The sys-proctable library is required to run this test suite.
23
+ You can find it at #{site} or the RAA.
24
+ Or, you can just 'gem install sys-proctable' and try again.
25
+ }
26
+ STDERR.puts msg
24
27
  exit!
25
28
  end
26
29
 
@@ -43,7 +46,7 @@ class TC_Win32Process < Test::Unit::TestCase
43
46
  end
44
47
 
45
48
  def test_version
46
- assert_equal('0.5.8', Process::WIN32_PROCESS_VERSION)
49
+ assert_equal('0.5.9', Process::WIN32_PROCESS_VERSION)
47
50
  end
48
51
 
49
52
  def test_kill
@@ -112,6 +115,12 @@ class TC_Win32Process < Test::Unit::TestCase
112
115
  def test_waitpid2
113
116
  assert_respond_to(Process, :waitpid2)
114
117
  end
118
+
119
+ def test_ppid
120
+ assert_respond_to(Process, :ppid)
121
+ assert_equal(true, Process.ppid > 0)
122
+ assert_equal(false, Process.pid == Process.ppid)
123
+ end
115
124
 
116
125
  def test_creation_constants
117
126
  assert_not_nil(Process::CREATE_DEFAULT_ERROR_MODE)
@@ -3,7 +3,7 @@ require "rubygems"
3
3
  spec = Gem::Specification.new do |gem|
4
4
  desc = "Adds create, fork, wait, wait2, waitpid, and a special kill method"
5
5
  gem.name = "win32-process"
6
- gem.version = "0.5.8"
6
+ gem.version = "0.5.9"
7
7
  gem.authors = ['Daniel Berger', 'Park Heesob']
8
8
  gem.email = "djberg96@gmail.com"
9
9
  gem.rubyforge_project = 'win32utils'
@@ -17,7 +17,7 @@ spec = Gem::Specification.new do |gem|
17
17
  gem.files.reject! { |fn| fn.include? "CVS" }
18
18
  gem.require_path = "lib"
19
19
  gem.extra_rdoc_files = ["README", "CHANGES", "MANIFEST"]
20
- gem.add_dependency("windows-pr", ">= 0.8.1")
20
+ gem.add_dependency("windows-pr", ">= 0.8.6")
21
21
  end
22
22
 
23
23
  if $0 == __FILE__
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: win32-process
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.8
4
+ version: 0.5.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Berger
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2008-04-24 00:00:00 -06:00
13
+ date: 2008-06-14 00:00:00 -06:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.8.1
23
+ version: 0.8.6
24
24
  version:
25
25
  description: Adds create, fork, wait, wait2, waitpid, and a special kill method
26
26
  email: djberg96@gmail.com