sleepy_penguin 3.2.0 → 3.3.0
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.
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +0 -1
- data/Rakefile +0 -37
- data/ext/sleepy_penguin/epoll.c +3 -15
- data/ext/sleepy_penguin/extconf.rb +9 -2
- data/ext/sleepy_penguin/init.c +59 -1
- data/ext/sleepy_penguin/inotify.c +16 -36
- data/ext/sleepy_penguin/kqueue.c +3 -15
- data/ext/sleepy_penguin/missing_clock_gettime.h +36 -0
- data/ext/sleepy_penguin/sleepy_penguin.h +1 -0
- data/ext/sleepy_penguin/util.c +16 -8
- data/ext/sleepy_penguin/value2timespec.h +2 -2
- data/test/helper.rb +17 -0
- data/test/test_constants.rb +2 -2
- data/test/test_epoll.rb +10 -9
- data/test/test_epoll_gc.rb +2 -2
- data/test/test_epoll_io.rb +2 -2
- data/test/test_epoll_optimizations.rb +2 -2
- data/test/test_eventfd.rb +3 -7
- data/test/test_inotify.rb +3 -7
- data/test/test_kqueue.rb +2 -2
- data/test/test_kqueue_io.rb +2 -2
- data/test/test_timerfd.rb +3 -7
- metadata +65 -60
- data/ext/sleepy_penguin/signalfd.c +0 -342
- data/test/test_signalfd.rb +0 -94
- data/test/test_signalfd_siginfo.rb +0 -32
@@ -42,8 +42,8 @@ static struct timespec *value2timespec(struct timespec *ts, VALUE num)
|
|
42
42
|
}}
|
43
43
|
{
|
44
44
|
VALUE tmp = rb_inspect(num);
|
45
|
-
|
46
|
-
|
45
|
+
const char *str = StringValueCStr(tmp);
|
46
|
+
rb_raise(rb_eTypeError, "can't convert %s into timespec", str);
|
47
47
|
}
|
48
48
|
rb_bug("rb_raise() failed, timespec failed");
|
49
49
|
return NULL;
|
data/test/helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
$-w = $stdout.sync = $stderr.sync = Thread.abort_on_exception = true
|
2
|
+
gem 'minitest'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
Testcase = begin
|
5
|
+
Minitest::Test # minitest 5
|
6
|
+
rescue NameError
|
7
|
+
Minitest::Unit::TestCase # minitest 4
|
8
|
+
end
|
9
|
+
|
10
|
+
def check_cloexec(io)
|
11
|
+
pipe = IO.pipe
|
12
|
+
rbimp = Fcntl::FD_CLOEXEC & pipe[0].fcntl(Fcntl::F_GETFD)
|
13
|
+
ours = Fcntl::FD_CLOEXEC & io.fcntl(Fcntl::F_GETFD)
|
14
|
+
assert_equal rbimp, ours, "CLOEXEC default does not match Ruby implementation"
|
15
|
+
ensure
|
16
|
+
pipe.each { |io| io.close }
|
17
|
+
end
|
data/test/test_constants.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'test/
|
1
|
+
require './test/helper'
|
2
2
|
$-w = true
|
3
3
|
Thread.abort_on_exception = true
|
4
4
|
require 'sleepy_penguin/sp'
|
5
5
|
|
6
|
-
class TestConstants <
|
6
|
+
class TestConstants < Testcase
|
7
7
|
def test_constants
|
8
8
|
assert_equal SleepyPenguin::SLEEPY_PENGUIN_VERSION,
|
9
9
|
SP::SLEEPY_PENGUIN_VERSION
|
data/test/test_epoll.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'test/
|
1
|
+
require './test/helper'
|
2
2
|
require 'fcntl'
|
3
3
|
require 'socket'
|
4
4
|
require 'thread'
|
@@ -7,7 +7,7 @@ Thread.abort_on_exception = true
|
|
7
7
|
|
8
8
|
require 'sleepy_penguin'
|
9
9
|
|
10
|
-
class TestEpoll <
|
10
|
+
class TestEpoll < Testcase
|
11
11
|
include SleepyPenguin
|
12
12
|
|
13
13
|
def setup
|
@@ -52,7 +52,7 @@ class TestEpoll < Test::Unit::TestCase
|
|
52
52
|
@ep.close
|
53
53
|
assert ! epdup.closed?
|
54
54
|
pid = fork do
|
55
|
-
exit(!epdup.closed? && @ep.closed?)
|
55
|
+
exit!(!epdup.closed? && @ep.closed?)
|
56
56
|
end
|
57
57
|
_, status = Process.waitpid2(pid)
|
58
58
|
assert status.success?, status.inspect
|
@@ -87,7 +87,12 @@ class TestEpoll < Test::Unit::TestCase
|
|
87
87
|
port = srv.addr[1]
|
88
88
|
addr = Socket.pack_sockaddr_in(port, host)
|
89
89
|
sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
90
|
-
|
90
|
+
begin
|
91
|
+
sock.connect_nonblock(addr)
|
92
|
+
exc = nil
|
93
|
+
rescue Errno::EINPROGRESS => exc
|
94
|
+
end
|
95
|
+
assert_kind_of Errno::EINPROGRESS, exc
|
91
96
|
IO.select(nil, [ sock ], [sock ])
|
92
97
|
@ep.add(sock, epflags)
|
93
98
|
tmp = []
|
@@ -343,11 +348,7 @@ class TestEpoll < Test::Unit::TestCase
|
|
343
348
|
def test_new
|
344
349
|
@ep.close
|
345
350
|
io = Epoll.new.to_io
|
346
|
-
|
347
|
-
assert_equal 1, io.fcntl(Fcntl::F_GETFD)
|
348
|
-
else
|
349
|
-
assert_equal 0, io.fcntl(Fcntl::F_GETFD)
|
350
|
-
end
|
351
|
+
check_cloexec(io)
|
351
352
|
end
|
352
353
|
|
353
354
|
def test_delete
|
data/test/test_epoll_gc.rb
CHANGED
data/test/test_epoll_io.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'test/
|
1
|
+
require './test/helper'
|
2
2
|
require 'fcntl'
|
3
3
|
require 'socket'
|
4
4
|
require 'thread'
|
@@ -6,7 +6,7 @@ $-w = true
|
|
6
6
|
Thread.abort_on_exception = true
|
7
7
|
require 'sleepy_penguin'
|
8
8
|
|
9
|
-
class TestEpollIO <
|
9
|
+
class TestEpollIO < Testcase
|
10
10
|
include SleepyPenguin
|
11
11
|
|
12
12
|
def setup
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'test/
|
1
|
+
require './test/helper'
|
2
2
|
begin
|
3
3
|
require 'strace'
|
4
4
|
rescue LoadError
|
@@ -7,7 +7,7 @@ $-w = true
|
|
7
7
|
|
8
8
|
require 'sleepy_penguin'
|
9
9
|
|
10
|
-
class TestEpollOptimizations <
|
10
|
+
class TestEpollOptimizations < Testcase
|
11
11
|
include SleepyPenguin
|
12
12
|
IO_PURGATORY = []
|
13
13
|
|
data/test/test_eventfd.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require 'test/
|
1
|
+
require './test/helper'
|
2
2
|
require 'fcntl'
|
3
3
|
$-w = true
|
4
4
|
|
5
5
|
require 'sleepy_penguin'
|
6
6
|
|
7
|
-
class TestEventFD <
|
7
|
+
class TestEventFD < Testcase
|
8
8
|
include SleepyPenguin
|
9
9
|
|
10
10
|
def test_constants
|
@@ -20,11 +20,7 @@ class TestEventFD < Test::Unit::TestCase
|
|
20
20
|
def test_new
|
21
21
|
efd = EventFD.new 0
|
22
22
|
assert_kind_of(IO, efd)
|
23
|
-
|
24
|
-
assert_equal 1, efd.fcntl(Fcntl::F_GETFD)
|
25
|
-
else
|
26
|
-
assert_equal 0, efd.fcntl(Fcntl::F_GETFD)
|
27
|
-
end
|
23
|
+
check_cloexec(efd)
|
28
24
|
end
|
29
25
|
|
30
26
|
def test_new_nonblock
|
data/test/test_inotify.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require 'test/
|
1
|
+
require './test/helper'
|
2
2
|
require 'fcntl'
|
3
3
|
require 'tempfile'
|
4
4
|
require 'set'
|
5
5
|
$-w = true
|
6
6
|
require 'sleepy_penguin'
|
7
7
|
|
8
|
-
class TestInotify <
|
8
|
+
class TestInotify < Testcase
|
9
9
|
include SleepyPenguin
|
10
10
|
attr_reader :ino
|
11
11
|
|
@@ -17,11 +17,7 @@ class TestInotify < Test::Unit::TestCase
|
|
17
17
|
def test_new
|
18
18
|
@ino = Inotify.new
|
19
19
|
assert_kind_of(IO, ino)
|
20
|
-
|
21
|
-
assert_equal 1, ino.fcntl(Fcntl::F_GETFD)
|
22
|
-
else
|
23
|
-
assert_equal 0, ino.fcntl(Fcntl::F_GETFD)
|
24
|
-
end
|
20
|
+
check_cloexec(ino)
|
25
21
|
end
|
26
22
|
|
27
23
|
def test_constants
|
data/test/test_kqueue.rb
CHANGED
data/test/test_kqueue_io.rb
CHANGED
data/test/test_timerfd.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require 'test/
|
1
|
+
require './test/helper'
|
2
2
|
require 'fcntl'
|
3
3
|
$-w = true
|
4
4
|
|
5
5
|
require 'sleepy_penguin'
|
6
6
|
|
7
|
-
class TestTimerFD <
|
7
|
+
class TestTimerFD < Testcase
|
8
8
|
include SleepyPenguin
|
9
9
|
|
10
10
|
def test_constants
|
@@ -15,11 +15,7 @@ class TestTimerFD < Test::Unit::TestCase
|
|
15
15
|
def test_create
|
16
16
|
tfd = TimerFD.new
|
17
17
|
assert_kind_of(IO, tfd)
|
18
|
-
|
19
|
-
assert_equal 1, tfd.fcntl(Fcntl::F_GETFD)
|
20
|
-
else
|
21
|
-
assert_equal 0, tfd.fcntl(Fcntl::F_GETFD)
|
22
|
-
end
|
18
|
+
check_cloexec(tfd)
|
23
19
|
end
|
24
20
|
|
25
21
|
def test_create_nonblock
|
metadata
CHANGED
@@ -1,61 +1,63 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: sleepy_penguin
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 3
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 3.3.0
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- sleepy_penguin hackers
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2013-12-30 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: wrongdoc
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '1.5'
|
22
|
-
type: :development
|
23
22
|
prerelease: false
|
24
|
-
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '1.5'
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: strace_me
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
33
24
|
none: false
|
34
|
-
requirements:
|
25
|
+
requirements:
|
35
26
|
- - ~>
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 5
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 5
|
32
|
+
version: "1.5"
|
38
33
|
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: strace_me
|
39
37
|
prerelease: false
|
40
|
-
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
42
|
-
requirements:
|
40
|
+
requirements:
|
43
41
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 15
|
44
|
+
segments:
|
45
|
+
- 1
|
46
|
+
- 0
|
47
|
+
version: "1.0"
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id002
|
50
|
+
description: |-
|
51
|
+
sleepy_penguin provides access to newer, Linux-only system calls to wait
|
49
52
|
on events from traditionally non-I/O sources. Bindings to the eventfd,
|
50
|
-
|
51
53
|
timerfd, inotify, and epoll interfaces are provided. Experimental support
|
52
|
-
|
53
|
-
for kqueue on FreeBSD (and likely OpenBSD/NetBSD) are also provided.'
|
54
|
+
for kqueue on FreeBSD (and likely OpenBSD/NetBSD) are also provided.
|
54
55
|
email: sleepy.penguin@librelist.org
|
55
56
|
executables: []
|
56
|
-
|
57
|
+
|
58
|
+
extensions:
|
57
59
|
- ext/sleepy_penguin/extconf.rb
|
58
|
-
extra_rdoc_files:
|
60
|
+
extra_rdoc_files:
|
59
61
|
- LICENSE
|
60
62
|
- README
|
61
63
|
- TODO
|
@@ -73,10 +75,9 @@ extra_rdoc_files:
|
|
73
75
|
- ext/sleepy_penguin/eventfd.c
|
74
76
|
- ext/sleepy_penguin/init.c
|
75
77
|
- ext/sleepy_penguin/inotify.c
|
76
|
-
- ext/sleepy_penguin/signalfd.c
|
77
78
|
- ext/sleepy_penguin/timerfd.c
|
78
79
|
- ext/sleepy_penguin/kqueue.c
|
79
|
-
files:
|
80
|
+
files:
|
80
81
|
- .document
|
81
82
|
- .gitignore
|
82
83
|
- .manifest
|
@@ -99,11 +100,11 @@ files:
|
|
99
100
|
- ext/sleepy_penguin/init.c
|
100
101
|
- ext/sleepy_penguin/inotify.c
|
101
102
|
- ext/sleepy_penguin/kqueue.c
|
103
|
+
- ext/sleepy_penguin/missing_clock_gettime.h
|
102
104
|
- ext/sleepy_penguin/missing_epoll.h
|
103
105
|
- ext/sleepy_penguin/missing_inotify.h
|
104
106
|
- ext/sleepy_penguin/missing_rb_thread_fd_close.h
|
105
107
|
- ext/sleepy_penguin/missing_rb_update_max_fd.h
|
106
|
-
- ext/sleepy_penguin/signalfd.c
|
107
108
|
- ext/sleepy_penguin/sleepy_penguin.h
|
108
109
|
- ext/sleepy_penguin/timerfd.c
|
109
110
|
- ext/sleepy_penguin/util.c
|
@@ -119,6 +120,7 @@ files:
|
|
119
120
|
- pkg.mk
|
120
121
|
- setup.rb
|
121
122
|
- sleepy_penguin.gemspec
|
123
|
+
- test/helper.rb
|
122
124
|
- test/test_constants.rb
|
123
125
|
- test/test_epoll.rb
|
124
126
|
- test/test_epoll_gc.rb
|
@@ -128,45 +130,48 @@ files:
|
|
128
130
|
- test/test_inotify.rb
|
129
131
|
- test/test_kqueue.rb
|
130
132
|
- test/test_kqueue_io.rb
|
131
|
-
- test/test_signalfd.rb
|
132
|
-
- test/test_signalfd_siginfo.rb
|
133
133
|
- test/test_timerfd.rb
|
134
134
|
homepage: http://bogomips.org/sleepy_penguin/
|
135
|
-
licenses:
|
135
|
+
licenses:
|
136
136
|
- LGPLv2.1
|
137
137
|
- LGPLv3
|
138
138
|
post_install_message:
|
139
|
-
rdoc_options:
|
139
|
+
rdoc_options:
|
140
140
|
- -t
|
141
141
|
- sleepy_penguin - Linux I/O events for Ruby
|
142
142
|
- -W
|
143
143
|
- http://bogomips.org/sleepy_penguin.git/tree/%s
|
144
|
-
require_paths:
|
144
|
+
require_paths:
|
145
145
|
- lib
|
146
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
147
147
|
none: false
|
148
|
-
requirements:
|
149
|
-
- -
|
150
|
-
- !ruby/object:Gem::Version
|
151
|
-
|
152
|
-
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
hash: 3
|
152
|
+
segments:
|
153
|
+
- 0
|
154
|
+
version: "0"
|
155
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
156
|
none: false
|
154
|
-
requirements:
|
155
|
-
- -
|
156
|
-
- !ruby/object:Gem::Version
|
157
|
-
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
hash: 3
|
161
|
+
segments:
|
162
|
+
- 0
|
163
|
+
version: "0"
|
158
164
|
requirements: []
|
165
|
+
|
159
166
|
rubyforge_project: rainbows
|
160
|
-
rubygems_version: 1.8.
|
167
|
+
rubygems_version: 1.8.24
|
161
168
|
signing_key:
|
162
169
|
specification_version: 3
|
163
170
|
summary: Linux I/O events for Ruby
|
164
|
-
test_files:
|
171
|
+
test_files:
|
165
172
|
- test/test_epoll_optimizations.rb
|
166
173
|
- test/test_constants.rb
|
167
|
-
- test/test_signalfd_siginfo.rb
|
168
174
|
- test/test_epoll.rb
|
169
|
-
- test/test_signalfd.rb
|
170
175
|
- test/test_kqueue_io.rb
|
171
176
|
- test/test_inotify.rb
|
172
177
|
- test/test_kqueue.rb
|
@@ -1,342 +0,0 @@
|
|
1
|
-
#ifdef HAVE_SYS_SIGNALFD_H
|
2
|
-
#include "sleepy_penguin.h"
|
3
|
-
#include <signal.h>
|
4
|
-
#include <sys/signalfd.h>
|
5
|
-
static VALUE ssi_members;
|
6
|
-
static VALUE cSigInfo;
|
7
|
-
|
8
|
-
/* converts a Symbol, String, or Fixnum to an integer signal */
|
9
|
-
static int sig2int(VALUE sig)
|
10
|
-
{
|
11
|
-
static VALUE list;
|
12
|
-
const char *ptr;
|
13
|
-
long len;
|
14
|
-
|
15
|
-
if (TYPE(sig) == T_FIXNUM)
|
16
|
-
return FIX2INT(sig);
|
17
|
-
|
18
|
-
sig = rb_obj_as_string(sig);
|
19
|
-
len = RSTRING_LEN(sig);
|
20
|
-
ptr = RSTRING_PTR(sig);
|
21
|
-
|
22
|
-
if (len > 3 && !memcmp("SIG", ptr, 3))
|
23
|
-
sig = rb_str_new(ptr + 3, len - 3);
|
24
|
-
|
25
|
-
if (!list) {
|
26
|
-
VALUE tmp = rb_const_get(rb_cObject, rb_intern("Signal"));
|
27
|
-
|
28
|
-
list = rb_funcall(tmp, rb_intern("list"), 0, 0);
|
29
|
-
rb_global_variable(&list);
|
30
|
-
}
|
31
|
-
|
32
|
-
sig = rb_hash_aref(list, sig);
|
33
|
-
if (NIL_P(sig))
|
34
|
-
rb_raise(rb_eArgError, "invalid signal: %s", ptr);
|
35
|
-
|
36
|
-
return NUM2INT(sig);
|
37
|
-
}
|
38
|
-
|
39
|
-
/* fills sigset_t with an Array of signals */
|
40
|
-
static void value2sigset(sigset_t *mask, VALUE set)
|
41
|
-
{
|
42
|
-
sigemptyset(mask);
|
43
|
-
|
44
|
-
switch (TYPE(set)) {
|
45
|
-
case T_NIL: return;
|
46
|
-
case T_ARRAY: {
|
47
|
-
VALUE *ptr = RARRAY_PTR(set);
|
48
|
-
long len = RARRAY_LEN(set);
|
49
|
-
|
50
|
-
while (--len >= 0)
|
51
|
-
sigaddset(mask, sig2int(*ptr++));
|
52
|
-
}
|
53
|
-
break;
|
54
|
-
default:
|
55
|
-
sigaddset(mask, sig2int(set));
|
56
|
-
}
|
57
|
-
}
|
58
|
-
|
59
|
-
static int cur_flags(int fd)
|
60
|
-
{
|
61
|
-
int rv = 0;
|
62
|
-
#ifdef SFD_CLOEXEC
|
63
|
-
{
|
64
|
-
int flags = fcntl(fd, F_GETFD);
|
65
|
-
if (flags == -1) rb_sys_fail("fcntl(F_GETFD)");
|
66
|
-
if (flags & FD_CLOEXEC) rv |= SFD_CLOEXEC;
|
67
|
-
}
|
68
|
-
#endif
|
69
|
-
#ifdef SFD_NONBLOCK
|
70
|
-
{
|
71
|
-
int flags = fcntl(fd, F_GETFL);
|
72
|
-
if (flags == -1) rb_sys_fail("fcntl(F_GETFL)");
|
73
|
-
if (flags & O_NONBLOCK) rv |= SFD_NONBLOCK;
|
74
|
-
}
|
75
|
-
#endif
|
76
|
-
return rv;
|
77
|
-
}
|
78
|
-
|
79
|
-
/*
|
80
|
-
* call-seq:
|
81
|
-
* sfd.update!(signals[, flags]) -> sfd
|
82
|
-
*
|
83
|
-
* Updates the signal mask watched for by the given +sfd+.
|
84
|
-
* Takes the same arguments as SignalFD.new.
|
85
|
-
*/
|
86
|
-
static VALUE update_bang(int argc, VALUE *argv, VALUE self)
|
87
|
-
{
|
88
|
-
VALUE vmask, vflags;
|
89
|
-
sigset_t mask;
|
90
|
-
int flags;
|
91
|
-
int fd = rb_sp_fileno(self);
|
92
|
-
int rc;
|
93
|
-
|
94
|
-
rb_scan_args(argc, argv, "02", &vmask, &vflags);
|
95
|
-
flags = NIL_P(vflags) ? cur_flags(fd)
|
96
|
-
: rb_sp_get_flags(self, vflags, 0);
|
97
|
-
value2sigset(&mask, vmask);
|
98
|
-
|
99
|
-
rc = signalfd(fd, &mask, flags);
|
100
|
-
if (rc < 0)
|
101
|
-
rb_sys_fail("signalfd");
|
102
|
-
return self;
|
103
|
-
}
|
104
|
-
|
105
|
-
/*
|
106
|
-
* call-seq:
|
107
|
-
* SignalFD.new(signals[, flags]) -> SignalFD IO object
|
108
|
-
*
|
109
|
-
* Creates a new SignalFD object to watch given +signals+ with +flags+.
|
110
|
-
*
|
111
|
-
* +signals+ is an Array of signal names or a single signal name that
|
112
|
-
* Signal.trap understands:
|
113
|
-
*
|
114
|
-
* signals = [ :USR1, "USR2" ]
|
115
|
-
* signals = :USR1
|
116
|
-
* signals = 15
|
117
|
-
*
|
118
|
-
* Starting with Linux 2.6.27, +flags+ may be a mask that consists of any
|
119
|
-
* of the following:
|
120
|
-
*
|
121
|
-
* - :CLOEXEC - set the close-on-exec flag on the new object
|
122
|
-
* - :NONBLOCK - set the non-blocking I/O flag on the new object
|
123
|
-
*/
|
124
|
-
static VALUE s_new(int argc, VALUE *argv, VALUE klass)
|
125
|
-
{
|
126
|
-
VALUE vmask, vflags, rv;
|
127
|
-
sigset_t mask;
|
128
|
-
int flags;
|
129
|
-
int fd;
|
130
|
-
|
131
|
-
rb_scan_args(argc, argv, "02", &vmask, &vflags);
|
132
|
-
flags = rb_sp_get_flags(klass, vflags, RB_SP_CLOEXEC(SFD_CLOEXEC));
|
133
|
-
value2sigset(&mask, vmask);
|
134
|
-
|
135
|
-
fd = signalfd(-1, &mask, flags);
|
136
|
-
if (fd < 0) {
|
137
|
-
if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
|
138
|
-
rb_gc();
|
139
|
-
fd = signalfd(-1, &mask, flags);
|
140
|
-
}
|
141
|
-
if (fd < 0)
|
142
|
-
rb_sys_fail("signalfd");
|
143
|
-
}
|
144
|
-
|
145
|
-
|
146
|
-
rv = INT2FIX(fd);
|
147
|
-
return rb_call_super(1, &rv);
|
148
|
-
}
|
149
|
-
|
150
|
-
static VALUE ssi_alloc(VALUE klass)
|
151
|
-
{
|
152
|
-
struct signalfd_siginfo *ssi = ALLOC(struct signalfd_siginfo);
|
153
|
-
|
154
|
-
return Data_Wrap_Struct(klass, NULL, -1, ssi);
|
155
|
-
}
|
156
|
-
|
157
|
-
/* :nodoc: */
|
158
|
-
static VALUE ssi_init(VALUE self)
|
159
|
-
{
|
160
|
-
struct signalfd_siginfo *ssi = DATA_PTR(self);
|
161
|
-
|
162
|
-
memset(ssi, 0, sizeof(struct signalfd_siginfo));
|
163
|
-
return self;
|
164
|
-
}
|
165
|
-
|
166
|
-
static VALUE sfd_read(void *args)
|
167
|
-
{
|
168
|
-
struct signalfd_siginfo *ssi = args;
|
169
|
-
int fd = ssi->ssi_fd;
|
170
|
-
ssize_t r = read(fd, ssi, sizeof(struct signalfd_siginfo));
|
171
|
-
|
172
|
-
return (VALUE)r;
|
173
|
-
}
|
174
|
-
|
175
|
-
/*
|
176
|
-
* call-seq:
|
177
|
-
* sfd.take([nonblock]) -> SignalFD::SigInfo object or +nil+
|
178
|
-
*
|
179
|
-
* Returns the next SigInfo object representing a received signal.
|
180
|
-
* If +nonblock+ is specified and true, this may return +nil+
|
181
|
-
*/
|
182
|
-
static VALUE sfd_take(int argc, VALUE *argv, VALUE self)
|
183
|
-
{
|
184
|
-
VALUE rv = ssi_alloc(cSigInfo);
|
185
|
-
struct signalfd_siginfo *ssi = DATA_PTR(rv);
|
186
|
-
ssize_t r;
|
187
|
-
int fd;
|
188
|
-
VALUE nonblock;
|
189
|
-
|
190
|
-
rb_scan_args(argc, argv, "01", &nonblock);
|
191
|
-
fd = rb_sp_fileno(self);
|
192
|
-
if (RTEST(nonblock))
|
193
|
-
rb_sp_set_nonblock(fd);
|
194
|
-
else
|
195
|
-
blocking_io_prepare(fd);
|
196
|
-
retry:
|
197
|
-
ssi->ssi_fd = fd;
|
198
|
-
r = (ssize_t)rb_sp_fd_region(sfd_read, ssi, fd);
|
199
|
-
if (r < 0) {
|
200
|
-
if (errno == EAGAIN && RTEST(nonblock))
|
201
|
-
return Qnil;
|
202
|
-
if (rb_sp_wait(rb_io_wait_readable, self, &fd))
|
203
|
-
goto retry;
|
204
|
-
rb_sys_fail("read(signalfd)");
|
205
|
-
}
|
206
|
-
if (r == 0)
|
207
|
-
rb_eof_error(); /* does this ever happen? */
|
208
|
-
return rv;
|
209
|
-
}
|
210
|
-
|
211
|
-
#define SSI_READER_FUNC(FN, FIELD) \
|
212
|
-
static VALUE ssi_##FIELD(VALUE self) { \
|
213
|
-
struct signalfd_siginfo *ssi = DATA_PTR(self); \
|
214
|
-
return FN(ssi->ssi_##FIELD); \
|
215
|
-
}
|
216
|
-
|
217
|
-
SSI_READER_FUNC(UINT2NUM,signo)
|
218
|
-
SSI_READER_FUNC(INT2NUM,errno)
|
219
|
-
SSI_READER_FUNC(INT2NUM,code)
|
220
|
-
SSI_READER_FUNC(UINT2NUM,pid)
|
221
|
-
SSI_READER_FUNC(UINT2NUM,uid)
|
222
|
-
SSI_READER_FUNC(INT2NUM,fd)
|
223
|
-
SSI_READER_FUNC(UINT2NUM,tid)
|
224
|
-
SSI_READER_FUNC(UINT2NUM,band)
|
225
|
-
SSI_READER_FUNC(UINT2NUM,overrun)
|
226
|
-
SSI_READER_FUNC(UINT2NUM,trapno)
|
227
|
-
SSI_READER_FUNC(INT2NUM,status)
|
228
|
-
SSI_READER_FUNC(INT2NUM,int)
|
229
|
-
SSI_READER_FUNC(ULL2NUM,ptr)
|
230
|
-
SSI_READER_FUNC(ULL2NUM,utime)
|
231
|
-
SSI_READER_FUNC(ULL2NUM,stime)
|
232
|
-
SSI_READER_FUNC(ULL2NUM,addr)
|
233
|
-
|
234
|
-
void sleepy_penguin_init_signalfd(void)
|
235
|
-
{
|
236
|
-
VALUE mSleepyPenguin, cSignalFD;
|
237
|
-
|
238
|
-
mSleepyPenguin = rb_define_module("SleepyPenguin");
|
239
|
-
|
240
|
-
/*
|
241
|
-
* Document-class: SleepyPenguin::SignalFD
|
242
|
-
*
|
243
|
-
* Use of this class is NOT recommended. Ruby itself has a great
|
244
|
-
* signal handling API and its implementation conflicts with this.
|
245
|
-
*
|
246
|
-
* This class is currently disabled and the documentation is only
|
247
|
-
* provided to describe what it would look like.
|
248
|
-
*
|
249
|
-
* A SignalFD is an IO object for accepting signals. It provides
|
250
|
-
* an alternative to Signal.trap that may be monitored using
|
251
|
-
* IO.select or Epoll.
|
252
|
-
*
|
253
|
-
* SignalFD appears interact unpredictably with YARV (Ruby 1.9) signal
|
254
|
-
* handling and has been unreliable in our testing. Since Ruby has a
|
255
|
-
* decent signal handling interface anyways, this class is less useful
|
256
|
-
* than signalfd() in a C-only environment.
|
257
|
-
*
|
258
|
-
* It is not supported at all.
|
259
|
-
*/
|
260
|
-
cSignalFD = rb_define_class_under(mSleepyPenguin, "SignalFD", rb_cIO);
|
261
|
-
|
262
|
-
/*
|
263
|
-
* Document-class: SleepyPenguin::SignalFD::SigInfo
|
264
|
-
*
|
265
|
-
* This class is returned by SignalFD#take. It consists of the
|
266
|
-
* following read-only members:
|
267
|
-
*
|
268
|
-
* - signo - signal number
|
269
|
-
* - errno - error number
|
270
|
-
* - code - signal code
|
271
|
-
* - pid - PID of sender
|
272
|
-
* - uid - real UID of sender
|
273
|
-
* - fd - file descriptor (SIGIO)
|
274
|
-
* - tid - kernel timer ID (POSIX timers)
|
275
|
-
* - band - band event (SIGIO)
|
276
|
-
* - overrun - POSIX timer overrun count
|
277
|
-
* - trapno - trap number that caused hardware-generated signal
|
278
|
-
* - exit status or signal (SIGCHLD)
|
279
|
-
* - int - integer sent by sigqueue(2)
|
280
|
-
* - ptr - Pointer sent by sigqueue(2)
|
281
|
-
* - utime - User CPU time consumed (SIGCHLD)
|
282
|
-
* - stime - System CPU time consumed (SIGCHLD)
|
283
|
-
* - addr - address that generated a hardware-generated signal
|
284
|
-
*/
|
285
|
-
cSigInfo = rb_define_class_under(cSignalFD, "SigInfo", rb_cObject);
|
286
|
-
rb_define_alloc_func(cSigInfo, ssi_alloc);
|
287
|
-
rb_define_private_method(cSigInfo, "initialize", ssi_init, 0);
|
288
|
-
|
289
|
-
/* TODO: si_code values */
|
290
|
-
|
291
|
-
rb_define_singleton_method(cSignalFD, "new", s_new, -1);
|
292
|
-
#ifdef SFD_NONBLOCK
|
293
|
-
NODOC_CONST(cSignalFD, "NONBLOCK", INT2NUM(SFD_NONBLOCK));
|
294
|
-
#endif
|
295
|
-
#ifdef SFD_CLOEXEC
|
296
|
-
NODOC_CONST(cSignalFD, "CLOEXEC", INT2NUM(SFD_CLOEXEC));
|
297
|
-
#endif
|
298
|
-
|
299
|
-
rb_define_method(cSignalFD, "take", sfd_take, -1);
|
300
|
-
rb_define_method(cSignalFD, "update!", update_bang, -1);
|
301
|
-
ssi_members = rb_ary_new();
|
302
|
-
|
303
|
-
NODOC_CONST(cSigInfo, "MEMBERS", ssi_members);
|
304
|
-
|
305
|
-
/*
|
306
|
-
* the minimum signal number for real-time signals,
|
307
|
-
* 34 on NPTL-based systems
|
308
|
-
*/
|
309
|
-
rb_define_const(cSignalFD, "RTMIN", INT2NUM(SIGRTMIN));
|
310
|
-
|
311
|
-
/*
|
312
|
-
* the maximum signal number for real-time signals,
|
313
|
-
* 64 on NPTL-based systems
|
314
|
-
*/
|
315
|
-
rb_define_const(cSignalFD, "RTMAX", INT2NUM(SIGRTMAX));
|
316
|
-
|
317
|
-
#define SSI_READER(FIELD) do { \
|
318
|
-
rb_define_method(cSigInfo, #FIELD, ssi_##FIELD, 0); \
|
319
|
-
rb_ary_push(ssi_members, ID2SYM(rb_intern(#FIELD))); \
|
320
|
-
} while (0)
|
321
|
-
|
322
|
-
SSI_READER(signo);
|
323
|
-
SSI_READER(errno);
|
324
|
-
SSI_READER(code);
|
325
|
-
SSI_READER(pid);
|
326
|
-
SSI_READER(uid);
|
327
|
-
SSI_READER(fd);
|
328
|
-
SSI_READER(tid);
|
329
|
-
SSI_READER(band);
|
330
|
-
SSI_READER(overrun);
|
331
|
-
SSI_READER(trapno);
|
332
|
-
SSI_READER(status);
|
333
|
-
SSI_READER(int);
|
334
|
-
SSI_READER(ptr);
|
335
|
-
SSI_READER(utime);
|
336
|
-
SSI_READER(stime);
|
337
|
-
SSI_READER(addr);
|
338
|
-
rb_obj_freeze(ssi_members);
|
339
|
-
|
340
|
-
rb_require("sleepy_penguin/signalfd/sig_info");
|
341
|
-
}
|
342
|
-
#endif /* HAVE_SYS_SIGNALFD_H */
|