sleepy_penguin 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 */
|