win32-job 0.1.2 → 0.1.3
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.
- checksums.yaml +4 -4
- data/CHANGES +5 -0
- data/MANIFEST +12 -12
- data/README +6 -0
- data/Rakefile +31 -31
- data/examples/example_job.rb +29 -29
- data/lib/win32/job.rb +5 -5
- data/lib/win32/job/constants.rb +65 -65
- data/lib/win32/job/helper.rb +26 -26
- data/lib/win32/job/structs.rb +175 -175
- data/test/test_win32_job.rb +1 -1
- data/win32-job.gemspec +1 -2
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af2229e6e9b4045eeee68046c86d250744c3e92c
|
4
|
+
data.tar.gz: a3f7373165c4826a3762424aacd85665bcd7da19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 843e8e7e12bb1f46957613139173307a922ed628ec41a6174c3171d6ff2b68052627c25d5d1471a0b83c4f338269564c04a6de0b716afb5df083de40f42d0903
|
7
|
+
data.tar.gz: 9e72222e7fa9327d642cbb31539d21e5bab9bad17ee4c77e50c7a02c9524cbaab7c7037ed9d73b0739aa66f785a53d6f1dd332c27477e3fd4d2ab4c9605f309e
|
data/CHANGES
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
= 0.1.3 - 20-Oct-2014
|
2
|
+
* Updates to the gem:create and gem:install tasks.
|
3
|
+
* Removed references to Rubyforge in the gemspec.
|
4
|
+
* Use relative_require where appropriate.
|
5
|
+
|
1
6
|
= 0.1.2 - 6-Feb-2014
|
2
7
|
* Altered the constructor. The second argument now controls whether or not
|
3
8
|
to raise an error if the job already exists. By default it will open the job
|
data/MANIFEST
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
* CHANGES
|
2
|
-
* MANIFEST
|
3
|
-
* Rakefile
|
4
|
-
* README
|
5
|
-
* win32-job.gemspec
|
6
|
-
* examples\example_job.rb
|
7
|
-
* lib\win32\job.rb
|
8
|
-
* lib\win32\job\constants.rb
|
9
|
-
* lib\win32\job\functions.rb
|
10
|
-
* lib\win32\job\helper.rb
|
11
|
-
* lib\win32\job\structs.rb
|
12
|
-
* test\test_win32_job.rb
|
1
|
+
* CHANGES
|
2
|
+
* MANIFEST
|
3
|
+
* Rakefile
|
4
|
+
* README
|
5
|
+
* win32-job.gemspec
|
6
|
+
* examples\example_job.rb
|
7
|
+
* lib\win32\job.rb
|
8
|
+
* lib\win32\job\constants.rb
|
9
|
+
* lib\win32\job\functions.rb
|
10
|
+
* lib\win32\job\helper.rb
|
11
|
+
* lib\win32\job\structs.rb
|
12
|
+
* test\test_win32_job.rb
|
data/README
CHANGED
@@ -35,6 +35,12 @@
|
|
35
35
|
== License
|
36
36
|
Artistic 2.0
|
37
37
|
|
38
|
+
== Contributions
|
39
|
+
Although this library is free, please consider having your company
|
40
|
+
setup a gittip if used by your company professionally.
|
41
|
+
|
42
|
+
http://www.gittip.com/djberg96/
|
43
|
+
|
38
44
|
== Copyright
|
39
45
|
(C) 2003-2014 Daniel J. Berger
|
40
46
|
All Rights Reserved
|
data/Rakefile
CHANGED
@@ -1,31 +1,31 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'rake/clean'
|
3
|
-
require 'rake/testtask'
|
4
|
-
|
5
|
-
CLEAN.include("**/*.gem", "**/*.rbc", "**/*.rbx")
|
6
|
-
|
7
|
-
namespace :gem do
|
8
|
-
desc 'Create the win32-job gem'
|
9
|
-
task :create do
|
10
|
-
spec = eval(IO.read('win32-job.gemspec'))
|
11
|
-
if Gem::VERSION < "2.0"
|
12
|
-
Gem::Builder.new(spec).build
|
13
|
-
else
|
14
|
-
require 'rubygems/package'
|
15
|
-
Gem::Package.build(spec)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
desc 'Install the win32-job gem'
|
20
|
-
task :install => [:create] do
|
21
|
-
file = Dir["*.gem"].first
|
22
|
-
sh "gem install #{file}"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
Rake::TestTask.new do |t|
|
27
|
-
t.verbose = true
|
28
|
-
t.warning = true
|
29
|
-
end
|
30
|
-
|
31
|
-
task :default => :test
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
CLEAN.include("**/*.gem", "**/*.rbc", "**/*.rbx")
|
6
|
+
|
7
|
+
namespace :gem do
|
8
|
+
desc 'Create the win32-job gem'
|
9
|
+
task :create => [:clean] do
|
10
|
+
spec = eval(IO.read('win32-job.gemspec'))
|
11
|
+
if Gem::VERSION < "2.0"
|
12
|
+
Gem::Builder.new(spec).build
|
13
|
+
else
|
14
|
+
require 'rubygems/package'
|
15
|
+
Gem::Package.build(spec)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Install the win32-job gem'
|
20
|
+
task :install => [:create] do
|
21
|
+
file = Dir["*.gem"].first
|
22
|
+
sh "gem install -l #{file}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Rake::TestTask.new do |t|
|
27
|
+
t.verbose = true
|
28
|
+
t.warning = true
|
29
|
+
end
|
30
|
+
|
31
|
+
task :default => :test
|
data/examples/example_job.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
-
#######################################################################
|
2
|
-
# example_job.rb
|
3
|
-
#
|
4
|
-
# Simple example script for futzing with Windows Jobs. This will fire
|
5
|
-
# up two instances of notepad and add them to the job, then close
|
6
|
-
# them.
|
7
|
-
#######################################################################
|
8
|
-
require 'win32/job'
|
9
|
-
include Win32
|
10
|
-
|
11
|
-
pid1 = Process.spawn("notepad.exe")
|
12
|
-
pid2 = Process.spawn("notepad.exe")
|
13
|
-
sleep 0.5
|
14
|
-
|
15
|
-
j = Job.new('test')
|
16
|
-
|
17
|
-
j.configure_limit(
|
18
|
-
:breakaway_ok => true,
|
19
|
-
:kill_on_job_close => true,
|
20
|
-
:process_memory => 1024 * 8,
|
21
|
-
:process_time => 1000
|
22
|
-
)
|
23
|
-
|
24
|
-
j.add_process(pid1)
|
25
|
-
j.add_process(pid2)
|
26
|
-
|
27
|
-
sleep 0.5
|
28
|
-
|
29
|
-
j.close # Notepad instances should terminate here, too.
|
1
|
+
#######################################################################
|
2
|
+
# example_job.rb
|
3
|
+
#
|
4
|
+
# Simple example script for futzing with Windows Jobs. This will fire
|
5
|
+
# up two instances of notepad and add them to the job, then close
|
6
|
+
# them.
|
7
|
+
#######################################################################
|
8
|
+
require 'win32/job'
|
9
|
+
include Win32
|
10
|
+
|
11
|
+
pid1 = Process.spawn("notepad.exe")
|
12
|
+
pid2 = Process.spawn("notepad.exe")
|
13
|
+
sleep 0.5
|
14
|
+
|
15
|
+
j = Job.new('test')
|
16
|
+
|
17
|
+
j.configure_limit(
|
18
|
+
:breakaway_ok => true,
|
19
|
+
:kill_on_job_close => true,
|
20
|
+
:process_memory => 1024 * 8,
|
21
|
+
:process_time => 1000
|
22
|
+
)
|
23
|
+
|
24
|
+
j.add_process(pid1)
|
25
|
+
j.add_process(pid2)
|
26
|
+
|
27
|
+
sleep 0.5
|
28
|
+
|
29
|
+
j.close # Notepad instances should terminate here, too.
|
data/lib/win32/job.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
require_relative 'job/constants'
|
2
|
+
require_relative 'job/functions'
|
3
|
+
require_relative 'job/structs'
|
4
|
+
require_relative 'job/helper'
|
5
5
|
|
6
6
|
# The Win32 module serves as a namespace only.
|
7
7
|
module Win32
|
@@ -14,7 +14,7 @@ module Win32
|
|
14
14
|
extend Windows::Functions
|
15
15
|
|
16
16
|
# The version of the win32-job library
|
17
|
-
VERSION = '0.1.
|
17
|
+
VERSION = '0.1.3'
|
18
18
|
|
19
19
|
private
|
20
20
|
|
data/lib/win32/job/constants.rb
CHANGED
@@ -1,65 +1,65 @@
|
|
1
|
-
require 'ffi'
|
2
|
-
|
3
|
-
module Windows
|
4
|
-
module Constants
|
5
|
-
private
|
6
|
-
|
7
|
-
JobObjectBasicAccountingInformation = 1
|
8
|
-
JobObjectBasicLimitInformation = 2
|
9
|
-
JobObjectBasicProcessIdList = 3
|
10
|
-
JobObjectBasicUIRestrictions = 4
|
11
|
-
JobObjectSecurityLimitInformation = 5
|
12
|
-
JobObjectEndOfJobTimeInformation = 6
|
13
|
-
JobObjectAssociateCompletionPortInformation = 7
|
14
|
-
JobObjectBasicAndIoAccountingInformation = 8
|
15
|
-
JobObjectExtendedLimitInformation = 9
|
16
|
-
JobObjectGroupInformation = 11
|
17
|
-
JobObjectNotificationLimitInformation = 12
|
18
|
-
JobObjectLimitViolationInformation = 13
|
19
|
-
JobObjectGroupInformationEx = 14
|
20
|
-
JobObjectCpuRateControlInformation = 15
|
21
|
-
|
22
|
-
PROCESS_ALL_ACCESS = 0x1F0FFF
|
23
|
-
PROCESS_SET_QUOTA = 0x0100
|
24
|
-
PROCESS_TERMINATE = 0x0001
|
25
|
-
SYNCHRONIZE = 0x00100000
|
26
|
-
|
27
|
-
INFINITE = 0xFFFFFFFF
|
28
|
-
|
29
|
-
INVALID_HANDLE_VALUE = FFI::Pointer.new(-1).address
|
30
|
-
ERROR_ALREADY_EXISTS = 183
|
31
|
-
|
32
|
-
JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 0x00000008
|
33
|
-
JOB_OBJECT_LIMIT_AFFINITY = 0x00000010
|
34
|
-
JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800
|
35
|
-
JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION = 0x00000400
|
36
|
-
JOB_OBJECT_LIMIT_JOB_MEMORY = 0x00000200
|
37
|
-
JOB_OBJECT_LIMIT_JOB_TIME = 0x00000004
|
38
|
-
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000
|
39
|
-
JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME = 0x00000040
|
40
|
-
JOB_OBJECT_LIMIT_PRIORITY_CLASS = 0x00000020
|
41
|
-
JOB_OBJECT_LIMIT_PROCESS_MEMORY = 0x00000100
|
42
|
-
JOB_OBJECT_LIMIT_PROCESS_TIME = 0x00000002
|
43
|
-
JOB_OBJECT_LIMIT_SCHEDULING_CLASS = 0x00000080
|
44
|
-
JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000
|
45
|
-
JOB_OBJECT_LIMIT_SUBSET_AFFINITY = 0x00004000
|
46
|
-
JOB_OBJECT_LIMIT_WORKINGSET = 0x00000001
|
47
|
-
|
48
|
-
JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO = 4
|
49
|
-
|
50
|
-
WAIT_ABANDONED = 0x00000080
|
51
|
-
WAIT_IO_COMPLETION = 0x000000C0
|
52
|
-
WAIT_OBJECT_0 = 0x00000000
|
53
|
-
WAIT_TIMEOUT = 0x00000102
|
54
|
-
WAIT_FAILED = 0xFFFFFFFF
|
55
|
-
|
56
|
-
public
|
57
|
-
|
58
|
-
ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000
|
59
|
-
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000
|
60
|
-
HIGH_PRIORITY_CLASS = 0x00000080
|
61
|
-
IDLE_PRIORITY_CLASS = 0x00000040
|
62
|
-
NORMAL_PRIORITY_CLASS = 0x00000020
|
63
|
-
REALTIME_PRIORITY_CLASS = 0x00000100
|
64
|
-
end
|
65
|
-
end
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module Windows
|
4
|
+
module Constants
|
5
|
+
private
|
6
|
+
|
7
|
+
JobObjectBasicAccountingInformation = 1
|
8
|
+
JobObjectBasicLimitInformation = 2
|
9
|
+
JobObjectBasicProcessIdList = 3
|
10
|
+
JobObjectBasicUIRestrictions = 4
|
11
|
+
JobObjectSecurityLimitInformation = 5
|
12
|
+
JobObjectEndOfJobTimeInformation = 6
|
13
|
+
JobObjectAssociateCompletionPortInformation = 7
|
14
|
+
JobObjectBasicAndIoAccountingInformation = 8
|
15
|
+
JobObjectExtendedLimitInformation = 9
|
16
|
+
JobObjectGroupInformation = 11
|
17
|
+
JobObjectNotificationLimitInformation = 12
|
18
|
+
JobObjectLimitViolationInformation = 13
|
19
|
+
JobObjectGroupInformationEx = 14
|
20
|
+
JobObjectCpuRateControlInformation = 15
|
21
|
+
|
22
|
+
PROCESS_ALL_ACCESS = 0x1F0FFF
|
23
|
+
PROCESS_SET_QUOTA = 0x0100
|
24
|
+
PROCESS_TERMINATE = 0x0001
|
25
|
+
SYNCHRONIZE = 0x00100000
|
26
|
+
|
27
|
+
INFINITE = 0xFFFFFFFF
|
28
|
+
|
29
|
+
INVALID_HANDLE_VALUE = FFI::Pointer.new(-1).address
|
30
|
+
ERROR_ALREADY_EXISTS = 183
|
31
|
+
|
32
|
+
JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 0x00000008
|
33
|
+
JOB_OBJECT_LIMIT_AFFINITY = 0x00000010
|
34
|
+
JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800
|
35
|
+
JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION = 0x00000400
|
36
|
+
JOB_OBJECT_LIMIT_JOB_MEMORY = 0x00000200
|
37
|
+
JOB_OBJECT_LIMIT_JOB_TIME = 0x00000004
|
38
|
+
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000
|
39
|
+
JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME = 0x00000040
|
40
|
+
JOB_OBJECT_LIMIT_PRIORITY_CLASS = 0x00000020
|
41
|
+
JOB_OBJECT_LIMIT_PROCESS_MEMORY = 0x00000100
|
42
|
+
JOB_OBJECT_LIMIT_PROCESS_TIME = 0x00000002
|
43
|
+
JOB_OBJECT_LIMIT_SCHEDULING_CLASS = 0x00000080
|
44
|
+
JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000
|
45
|
+
JOB_OBJECT_LIMIT_SUBSET_AFFINITY = 0x00004000
|
46
|
+
JOB_OBJECT_LIMIT_WORKINGSET = 0x00000001
|
47
|
+
|
48
|
+
JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO = 4
|
49
|
+
|
50
|
+
WAIT_ABANDONED = 0x00000080
|
51
|
+
WAIT_IO_COMPLETION = 0x000000C0
|
52
|
+
WAIT_OBJECT_0 = 0x00000000
|
53
|
+
WAIT_TIMEOUT = 0x00000102
|
54
|
+
WAIT_FAILED = 0xFFFFFFFF
|
55
|
+
|
56
|
+
public
|
57
|
+
|
58
|
+
ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000
|
59
|
+
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000
|
60
|
+
HIGH_PRIORITY_CLASS = 0x00000080
|
61
|
+
IDLE_PRIORITY_CLASS = 0x00000040
|
62
|
+
NORMAL_PRIORITY_CLASS = 0x00000020
|
63
|
+
REALTIME_PRIORITY_CLASS = 0x00000100
|
64
|
+
end
|
65
|
+
end
|
data/lib/win32/job/helper.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
-
require 'ffi'
|
2
|
-
|
3
|
-
module FFI
|
4
|
-
extend FFI::Library
|
5
|
-
|
6
|
-
ffi_lib :kernel32
|
7
|
-
|
8
|
-
attach_function :FormatMessage, :FormatMessageA,
|
9
|
-
[:ulong, :pointer, :ulong, :ulong, :pointer, :ulong, :pointer], :ulong
|
10
|
-
|
11
|
-
def win_error(function, err=FFI.errno)
|
12
|
-
flags = 0x00001000 | 0x00000200
|
13
|
-
buf = FFI::MemoryPointer.new(:char, 1024)
|
14
|
-
|
15
|
-
FormatMessage(flags, nil, err , 0x0409, buf, 1024, nil)
|
16
|
-
|
17
|
-
function + ': ' + buf.read_string.strip
|
18
|
-
end
|
19
|
-
|
20
|
-
def raise_windows_error(function, err=FFI.errno)
|
21
|
-
raise SystemCallError.new(win_error(function, err), err)
|
22
|
-
end
|
23
|
-
|
24
|
-
module_function :win_error
|
25
|
-
module_function :raise_windows_error
|
26
|
-
end
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module FFI
|
4
|
+
extend FFI::Library
|
5
|
+
|
6
|
+
ffi_lib :kernel32
|
7
|
+
|
8
|
+
attach_function :FormatMessage, :FormatMessageA,
|
9
|
+
[:ulong, :pointer, :ulong, :ulong, :pointer, :ulong, :pointer], :ulong
|
10
|
+
|
11
|
+
def win_error(function, err=FFI.errno)
|
12
|
+
flags = 0x00001000 | 0x00000200
|
13
|
+
buf = FFI::MemoryPointer.new(:char, 1024)
|
14
|
+
|
15
|
+
FormatMessage(flags, nil, err , 0x0409, buf, 1024, nil)
|
16
|
+
|
17
|
+
function + ': ' + buf.read_string.strip
|
18
|
+
end
|
19
|
+
|
20
|
+
def raise_windows_error(function, err=FFI.errno)
|
21
|
+
raise SystemCallError.new(win_error(function, err), err)
|
22
|
+
end
|
23
|
+
|
24
|
+
module_function :win_error
|
25
|
+
module_function :raise_windows_error
|
26
|
+
end
|
data/lib/win32/job/structs.rb
CHANGED
@@ -1,175 +1,175 @@
|
|
1
|
-
require 'ffi'
|
2
|
-
|
3
|
-
module Windows
|
4
|
-
module Structs
|
5
|
-
extend FFI::Library
|
6
|
-
|
7
|
-
typedef :uintptr_t, :handle
|
8
|
-
typedef :ulong, :dword
|
9
|
-
typedef :ushort, :word
|
10
|
-
|
11
|
-
class LARGE_INTEGER < FFI::Union
|
12
|
-
layout(:QuadPart, :long_long)
|
13
|
-
end
|
14
|
-
|
15
|
-
class JOBOBJECT_BASIC_PROCESS_ID_LIST < FFI::Struct
|
16
|
-
layout(
|
17
|
-
:NumberOfAssignedProcesses, :ulong,
|
18
|
-
:NumberOfProcessIdsInList, :ulong,
|
19
|
-
:ProcessIdList, [:uintptr_t, 100] # Limit 100 processes per job (?)
|
20
|
-
)
|
21
|
-
end
|
22
|
-
|
23
|
-
class JOBOBJECT_BASIC_ACCOUNTING_INFORMATION < FFI::Struct
|
24
|
-
layout(
|
25
|
-
:TotalUserTime, LARGE_INTEGER,
|
26
|
-
:TotalKernelTime, LARGE_INTEGER,
|
27
|
-
:ThisPeriodTotalUserTime, LARGE_INTEGER,
|
28
|
-
:ThisPeriodTotalKernelTime, LARGE_INTEGER,
|
29
|
-
:TotalPageFaultCount, :ulong,
|
30
|
-
:TotalProcesses, :ulong,
|
31
|
-
:ActiveProcesses, :ulong,
|
32
|
-
:TotalTerminatedProcesses, :ulong
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
|
-
class IO_COUNTERS < FFI::Struct
|
37
|
-
layout(
|
38
|
-
:ReadOperationCount, :ulong_long,
|
39
|
-
:WriteOperationCount, :ulong_long,
|
40
|
-
:OtherOperationCount, :ulong_long,
|
41
|
-
:ReadTransferCount, :ulong_long,
|
42
|
-
:WriteTransferCount, :ulong_long,
|
43
|
-
:OtherTransferCount, :ulong_long
|
44
|
-
)
|
45
|
-
end
|
46
|
-
|
47
|
-
class JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION < FFI::Struct
|
48
|
-
layout(
|
49
|
-
:BasicInfo, JOBOBJECT_BASIC_ACCOUNTING_INFORMATION,
|
50
|
-
:IoInfo, IO_COUNTERS
|
51
|
-
)
|
52
|
-
end
|
53
|
-
|
54
|
-
class JOBOBJECT_BASIC_LIMIT_INFORMATION < FFI::Struct
|
55
|
-
layout(
|
56
|
-
:PerProcessUserTimeLimit, LARGE_INTEGER,
|
57
|
-
:PerJobUserTimeLimit, LARGE_INTEGER,
|
58
|
-
:LimitFlags, :ulong,
|
59
|
-
:MinimumWorkingSetSize, :size_t,
|
60
|
-
:MaximumWorkingSetSize, :size_t,
|
61
|
-
:ActiveProcessLimit, :ulong,
|
62
|
-
:Affinity, :uintptr_t,
|
63
|
-
:PriorityClass, :ulong,
|
64
|
-
:SchedulingClass, :ulong
|
65
|
-
)
|
66
|
-
end
|
67
|
-
|
68
|
-
class JOBOBJECT_EXTENDED_LIMIT_INFORMATION < FFI::Struct
|
69
|
-
layout(
|
70
|
-
:BasicLimitInformation, JOBOBJECT_BASIC_LIMIT_INFORMATION,
|
71
|
-
:IoInfo, IO_COUNTERS,
|
72
|
-
:ProcessMemoryLimit, :size_t,
|
73
|
-
:JobMemoryLimit, :size_t,
|
74
|
-
:PeakProcessMemoryUsed, :size_t,
|
75
|
-
:PeakJobMemoryUsed, :size_t
|
76
|
-
)
|
77
|
-
end
|
78
|
-
|
79
|
-
class JOBOBJECT_ASSOCIATE_COMPLETION_PORT < FFI::Struct
|
80
|
-
layout(:CompletionKey, :uintptr_t, :CompletionPort, :handle)
|
81
|
-
end
|
82
|
-
|
83
|
-
class SECURITY_ATTRIBUTES < FFI::Struct
|
84
|
-
layout(
|
85
|
-
:nLength, :ulong,
|
86
|
-
:lpSecurityDescriptor, :pointer,
|
87
|
-
:bInheritHandle, :bool
|
88
|
-
)
|
89
|
-
end
|
90
|
-
|
91
|
-
class PROCESS_INFORMATION < FFI::Struct
|
92
|
-
layout(
|
93
|
-
:hProcess, :handle,
|
94
|
-
:hThread, :handle,
|
95
|
-
:dwProcessId, :dword,
|
96
|
-
:dwThreadId, :dword
|
97
|
-
)
|
98
|
-
end
|
99
|
-
|
100
|
-
class STARTUPINFO < FFI::Struct
|
101
|
-
layout(
|
102
|
-
:cb, :ulong,
|
103
|
-
:lpReserved, :string,
|
104
|
-
:lpDesktop, :string,
|
105
|
-
:lpTitle, :string,
|
106
|
-
:dwX, :dword,
|
107
|
-
:dwY, :dword,
|
108
|
-
:dwXSize, :dword,
|
109
|
-
:dwYSize, :dword,
|
110
|
-
:dwXCountChars, :dword,
|
111
|
-
:dwYCountChars, :dword,
|
112
|
-
:dwFillAttribute, :dword,
|
113
|
-
:dwFlags, :dword,
|
114
|
-
:wShowWindow, :word,
|
115
|
-
:cbReserved2, :word,
|
116
|
-
:lpReserved2, :pointer,
|
117
|
-
:hStdInput, :handle,
|
118
|
-
:hStdOutput, :handle,
|
119
|
-
:hStdError, :handle
|
120
|
-
)
|
121
|
-
end
|
122
|
-
|
123
|
-
# I'm assuming the anonymous struct for the internal union here.
|
124
|
-
class Overlapped < FFI::Struct
|
125
|
-
layout(
|
126
|
-
:Internal, :ulong,
|
127
|
-
:InternalHigh, :ulong,
|
128
|
-
:Offset, :ulong,
|
129
|
-
:OffsetHigh, :ulong,
|
130
|
-
:hEvent, :ulong
|
131
|
-
)
|
132
|
-
end
|
133
|
-
|
134
|
-
# Ruby Structs
|
135
|
-
|
136
|
-
AccountInfo = Struct.new('AccountInfo',
|
137
|
-
:total_user_time,
|
138
|
-
:total_kernel_time,
|
139
|
-
:this_period_total_user_time,
|
140
|
-
:this_period_total_kernel_time,
|
141
|
-
:total_page_fault_count,
|
142
|
-
:total_processes,
|
143
|
-
:active_processes,
|
144
|
-
:total_terminated_processes,
|
145
|
-
:read_operation_count,
|
146
|
-
:write_operation_count,
|
147
|
-
:other_operation_count,
|
148
|
-
:read_transfer_count,
|
149
|
-
:write_transfer_count,
|
150
|
-
:other_transfer_count
|
151
|
-
)
|
152
|
-
|
153
|
-
LimitInfo = Struct.new('LimitInfo',
|
154
|
-
:per_process_user_time_limit,
|
155
|
-
:per_job_user_time_limit,
|
156
|
-
:limit_flags,
|
157
|
-
:minimum_working_set_size,
|
158
|
-
:maximum_working_set_size,
|
159
|
-
:active_process_limit,
|
160
|
-
:affinity,
|
161
|
-
:priority_class,
|
162
|
-
:scheduling_class,
|
163
|
-
:read_operation_count,
|
164
|
-
:write_operation_count,
|
165
|
-
:other_operation_count,
|
166
|
-
:read_transfer_count,
|
167
|
-
:write_transfer_count,
|
168
|
-
:other_transfer_count,
|
169
|
-
:process_memory_limit,
|
170
|
-
:job_memory_limit,
|
171
|
-
:peak_process_memory_used,
|
172
|
-
:peek_job_memory_used
|
173
|
-
)
|
174
|
-
end
|
175
|
-
end
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module Windows
|
4
|
+
module Structs
|
5
|
+
extend FFI::Library
|
6
|
+
|
7
|
+
typedef :uintptr_t, :handle
|
8
|
+
typedef :ulong, :dword
|
9
|
+
typedef :ushort, :word
|
10
|
+
|
11
|
+
class LARGE_INTEGER < FFI::Union
|
12
|
+
layout(:QuadPart, :long_long)
|
13
|
+
end
|
14
|
+
|
15
|
+
class JOBOBJECT_BASIC_PROCESS_ID_LIST < FFI::Struct
|
16
|
+
layout(
|
17
|
+
:NumberOfAssignedProcesses, :ulong,
|
18
|
+
:NumberOfProcessIdsInList, :ulong,
|
19
|
+
:ProcessIdList, [:uintptr_t, 100] # Limit 100 processes per job (?)
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
class JOBOBJECT_BASIC_ACCOUNTING_INFORMATION < FFI::Struct
|
24
|
+
layout(
|
25
|
+
:TotalUserTime, LARGE_INTEGER,
|
26
|
+
:TotalKernelTime, LARGE_INTEGER,
|
27
|
+
:ThisPeriodTotalUserTime, LARGE_INTEGER,
|
28
|
+
:ThisPeriodTotalKernelTime, LARGE_INTEGER,
|
29
|
+
:TotalPageFaultCount, :ulong,
|
30
|
+
:TotalProcesses, :ulong,
|
31
|
+
:ActiveProcesses, :ulong,
|
32
|
+
:TotalTerminatedProcesses, :ulong
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
class IO_COUNTERS < FFI::Struct
|
37
|
+
layout(
|
38
|
+
:ReadOperationCount, :ulong_long,
|
39
|
+
:WriteOperationCount, :ulong_long,
|
40
|
+
:OtherOperationCount, :ulong_long,
|
41
|
+
:ReadTransferCount, :ulong_long,
|
42
|
+
:WriteTransferCount, :ulong_long,
|
43
|
+
:OtherTransferCount, :ulong_long
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
class JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION < FFI::Struct
|
48
|
+
layout(
|
49
|
+
:BasicInfo, JOBOBJECT_BASIC_ACCOUNTING_INFORMATION,
|
50
|
+
:IoInfo, IO_COUNTERS
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
class JOBOBJECT_BASIC_LIMIT_INFORMATION < FFI::Struct
|
55
|
+
layout(
|
56
|
+
:PerProcessUserTimeLimit, LARGE_INTEGER,
|
57
|
+
:PerJobUserTimeLimit, LARGE_INTEGER,
|
58
|
+
:LimitFlags, :ulong,
|
59
|
+
:MinimumWorkingSetSize, :size_t,
|
60
|
+
:MaximumWorkingSetSize, :size_t,
|
61
|
+
:ActiveProcessLimit, :ulong,
|
62
|
+
:Affinity, :uintptr_t,
|
63
|
+
:PriorityClass, :ulong,
|
64
|
+
:SchedulingClass, :ulong
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
class JOBOBJECT_EXTENDED_LIMIT_INFORMATION < FFI::Struct
|
69
|
+
layout(
|
70
|
+
:BasicLimitInformation, JOBOBJECT_BASIC_LIMIT_INFORMATION,
|
71
|
+
:IoInfo, IO_COUNTERS,
|
72
|
+
:ProcessMemoryLimit, :size_t,
|
73
|
+
:JobMemoryLimit, :size_t,
|
74
|
+
:PeakProcessMemoryUsed, :size_t,
|
75
|
+
:PeakJobMemoryUsed, :size_t
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
class JOBOBJECT_ASSOCIATE_COMPLETION_PORT < FFI::Struct
|
80
|
+
layout(:CompletionKey, :uintptr_t, :CompletionPort, :handle)
|
81
|
+
end
|
82
|
+
|
83
|
+
class SECURITY_ATTRIBUTES < FFI::Struct
|
84
|
+
layout(
|
85
|
+
:nLength, :ulong,
|
86
|
+
:lpSecurityDescriptor, :pointer,
|
87
|
+
:bInheritHandle, :bool
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
class PROCESS_INFORMATION < FFI::Struct
|
92
|
+
layout(
|
93
|
+
:hProcess, :handle,
|
94
|
+
:hThread, :handle,
|
95
|
+
:dwProcessId, :dword,
|
96
|
+
:dwThreadId, :dword
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
class STARTUPINFO < FFI::Struct
|
101
|
+
layout(
|
102
|
+
:cb, :ulong,
|
103
|
+
:lpReserved, :string,
|
104
|
+
:lpDesktop, :string,
|
105
|
+
:lpTitle, :string,
|
106
|
+
:dwX, :dword,
|
107
|
+
:dwY, :dword,
|
108
|
+
:dwXSize, :dword,
|
109
|
+
:dwYSize, :dword,
|
110
|
+
:dwXCountChars, :dword,
|
111
|
+
:dwYCountChars, :dword,
|
112
|
+
:dwFillAttribute, :dword,
|
113
|
+
:dwFlags, :dword,
|
114
|
+
:wShowWindow, :word,
|
115
|
+
:cbReserved2, :word,
|
116
|
+
:lpReserved2, :pointer,
|
117
|
+
:hStdInput, :handle,
|
118
|
+
:hStdOutput, :handle,
|
119
|
+
:hStdError, :handle
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
# I'm assuming the anonymous struct for the internal union here.
|
124
|
+
class Overlapped < FFI::Struct
|
125
|
+
layout(
|
126
|
+
:Internal, :ulong,
|
127
|
+
:InternalHigh, :ulong,
|
128
|
+
:Offset, :ulong,
|
129
|
+
:OffsetHigh, :ulong,
|
130
|
+
:hEvent, :ulong
|
131
|
+
)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Ruby Structs
|
135
|
+
|
136
|
+
AccountInfo = Struct.new('AccountInfo',
|
137
|
+
:total_user_time,
|
138
|
+
:total_kernel_time,
|
139
|
+
:this_period_total_user_time,
|
140
|
+
:this_period_total_kernel_time,
|
141
|
+
:total_page_fault_count,
|
142
|
+
:total_processes,
|
143
|
+
:active_processes,
|
144
|
+
:total_terminated_processes,
|
145
|
+
:read_operation_count,
|
146
|
+
:write_operation_count,
|
147
|
+
:other_operation_count,
|
148
|
+
:read_transfer_count,
|
149
|
+
:write_transfer_count,
|
150
|
+
:other_transfer_count
|
151
|
+
)
|
152
|
+
|
153
|
+
LimitInfo = Struct.new('LimitInfo',
|
154
|
+
:per_process_user_time_limit,
|
155
|
+
:per_job_user_time_limit,
|
156
|
+
:limit_flags,
|
157
|
+
:minimum_working_set_size,
|
158
|
+
:maximum_working_set_size,
|
159
|
+
:active_process_limit,
|
160
|
+
:affinity,
|
161
|
+
:priority_class,
|
162
|
+
:scheduling_class,
|
163
|
+
:read_operation_count,
|
164
|
+
:write_operation_count,
|
165
|
+
:other_operation_count,
|
166
|
+
:read_transfer_count,
|
167
|
+
:write_transfer_count,
|
168
|
+
:other_transfer_count,
|
169
|
+
:process_memory_limit,
|
170
|
+
:job_memory_limit,
|
171
|
+
:peak_process_memory_used,
|
172
|
+
:peek_job_memory_used
|
173
|
+
)
|
174
|
+
end
|
175
|
+
end
|
data/test/test_win32_job.rb
CHANGED
data/win32-job.gemspec
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'win32-job'
|
5
|
-
spec.version = '0.1.
|
5
|
+
spec.version = '0.1.3'
|
6
6
|
spec.authors = ['Daniel J. Berger', 'Park Heesob']
|
7
7
|
spec.license = 'Artistic 2.0'
|
8
8
|
spec.email = 'djberg96@gmail.com'
|
@@ -12,7 +12,6 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
|
13
13
|
|
14
14
|
spec.extra_rdoc_files = ['README', 'CHANGES', 'MANIFEST']
|
15
|
-
spec.rubyforge_project = 'win32utils'
|
16
15
|
spec.required_ruby_version = '> 1.9.3'
|
17
16
|
|
18
17
|
spec.add_dependency('ffi')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win32-job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
@@ -9,48 +9,48 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-10-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- -
|
18
|
+
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '0'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rake
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- -
|
32
|
+
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '0'
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- -
|
39
|
+
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: test-unit
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- -
|
46
|
+
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '0'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- -
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
56
|
description: |2
|
@@ -87,16 +87,16 @@ require_paths:
|
|
87
87
|
- lib
|
88
88
|
required_ruby_version: !ruby/object:Gem::Requirement
|
89
89
|
requirements:
|
90
|
-
- -
|
90
|
+
- - ">"
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: 1.9.3
|
93
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
|
-
- -
|
95
|
+
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
98
|
requirements: []
|
99
|
-
rubyforge_project:
|
99
|
+
rubyforge_project:
|
100
100
|
rubygems_version: 2.2.2
|
101
101
|
signing_key:
|
102
102
|
specification_version: 4
|