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 +3 -0
- data/README +16 -12
- data/lib/win32/process.rb +44 -3
- data/test/tc_process.rb +15 -6
- data/win32-process.gemspec +2 -2
- metadata +3 -3
data/CHANGES
CHANGED
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.
|
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.
|
9
|
-
The 'sys-proctable' library, 0.7.
|
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.
|
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.
|
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.
|
57
|
-
GUI processes.
|
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.
|
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.
|
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.
|
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
|
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
|
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
|
-
|
22
|
-
|
23
|
-
|
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.
|
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)
|
data/win32-process.gemspec
CHANGED
@@ -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.
|
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.
|
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.
|
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-
|
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.
|
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
|