io-nonblock 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/io/nonblock/extconf.rb +7 -0
- data/ext/io/nonblock/nonblock.c +99 -33
- metadata +6 -12
- data/.gitignore +0 -11
- data/.travis.yml +0 -6
- data/Gemfile +0 -4
- data/Rakefile +0 -12
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/io-nonblock.gemspec +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72722b1ffc6a232b51665e937ecabe164a15e2dbccdb35628fe158db78e56713
|
4
|
+
data.tar.gz: 491aa2cbbb825667d190e5dca3f3ef44abb7fcc65d2a5080e33f5fa4936142f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c1e8c2abd77710e460dc12c39a89f2bf3e2466208bc422e97ec1891629d71d569c95c8b80beadd0ef5f5673c53f4101f016930038770266b2f62732972f7b65
|
7
|
+
data.tar.gz: 3045f739c5bdcbef2c1335bfd0024842e5be44d0af0a3a90fb49c3ca9151fa02e74520cc854b3207e328b8c1a7f19fde5b580ad121c511590860e484de5b335d
|
data/ext/io/nonblock/extconf.rb
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
require 'mkmf'
|
3
3
|
target = "io/nonblock"
|
4
4
|
|
5
|
+
unless RUBY_ENGINE == 'ruby'
|
6
|
+
File.write("Makefile", dummy_makefile($srcdir).join(""))
|
7
|
+
return
|
8
|
+
end
|
9
|
+
|
10
|
+
have_func("rb_io_descriptor")
|
11
|
+
|
5
12
|
hdr = %w"fcntl.h"
|
6
13
|
if have_macro("O_NONBLOCK", hdr) and
|
7
14
|
(have_macro("F_GETFL", hdr) or have_macro("F_SETFL", hdr))
|
data/ext/io/nonblock/nonblock.c
CHANGED
@@ -17,16 +17,27 @@
|
|
17
17
|
#endif
|
18
18
|
#include <fcntl.h>
|
19
19
|
|
20
|
+
#ifndef HAVE_RB_IO_DESCRIPTOR
|
21
|
+
static int
|
22
|
+
io_descriptor_fallback(VALUE io)
|
23
|
+
{
|
24
|
+
rb_io_t *fptr;
|
25
|
+
GetOpenFile(io, fptr);
|
26
|
+
return fptr->fd;
|
27
|
+
}
|
28
|
+
#define rb_io_descriptor io_descriptor_fallback
|
29
|
+
#endif
|
30
|
+
|
20
31
|
#ifdef F_GETFL
|
21
32
|
static int
|
22
|
-
|
33
|
+
get_fcntl_flags(int fd)
|
23
34
|
{
|
24
35
|
int f = fcntl(fd, F_GETFL);
|
25
36
|
if (f == -1) rb_sys_fail(0);
|
26
37
|
return f;
|
27
38
|
}
|
28
39
|
#else
|
29
|
-
#define
|
40
|
+
#define get_fcntl_flags(fd) ((void)(fd), 0)
|
30
41
|
#endif
|
31
42
|
|
32
43
|
#ifdef F_GETFL
|
@@ -39,10 +50,8 @@ io_nonblock_mode(int fd)
|
|
39
50
|
static VALUE
|
40
51
|
rb_io_nonblock_p(VALUE io)
|
41
52
|
{
|
42
|
-
|
43
|
-
|
44
|
-
if (io_nonblock_mode(fptr->fd) & O_NONBLOCK)
|
45
|
-
return Qtrue;
|
53
|
+
if (get_fcntl_flags(rb_io_descriptor(io)) & O_NONBLOCK)
|
54
|
+
return Qtrue;
|
46
55
|
return Qfalse;
|
47
56
|
}
|
48
57
|
#else
|
@@ -50,6 +59,15 @@ rb_io_nonblock_p(VALUE io)
|
|
50
59
|
#endif
|
51
60
|
|
52
61
|
#ifdef F_SETFL
|
62
|
+
static void
|
63
|
+
set_fcntl_flags(int fd, int f)
|
64
|
+
{
|
65
|
+
if (fcntl(fd, F_SETFL, f) == -1)
|
66
|
+
rb_sys_fail(0);
|
67
|
+
}
|
68
|
+
|
69
|
+
#ifndef RUBY_IO_NONBLOCK_METHODS
|
70
|
+
|
53
71
|
static int
|
54
72
|
io_nonblock_set(int fd, int f, int nb)
|
55
73
|
{
|
@@ -63,8 +81,7 @@ io_nonblock_set(int fd, int f, int nb)
|
|
63
81
|
return 0;
|
64
82
|
f &= ~O_NONBLOCK;
|
65
83
|
}
|
66
|
-
|
67
|
-
rb_sys_fail(0);
|
84
|
+
set_fcntl_flags(fd, f);
|
68
85
|
return 1;
|
69
86
|
}
|
70
87
|
|
@@ -74,32 +91,77 @@ io_nonblock_set(int fd, int f, int nb)
|
|
74
91
|
*
|
75
92
|
* Enables non-blocking mode on a stream when set to
|
76
93
|
* +true+, and blocking mode when set to +false+.
|
94
|
+
*
|
95
|
+
* This method set or clear O_NONBLOCK flag for the file descriptor
|
96
|
+
* in <em>ios</em>.
|
97
|
+
*
|
98
|
+
* The behavior of most IO methods is not affected by this flag
|
99
|
+
* because they retry system calls to complete their task
|
100
|
+
* after EAGAIN and partial read/write.
|
101
|
+
* (An exception is IO#syswrite which doesn't retry.)
|
102
|
+
*
|
103
|
+
* This method can be used to clear non-blocking mode of standard I/O.
|
104
|
+
* Since nonblocking methods (read_nonblock, etc.) set non-blocking mode but
|
105
|
+
* they doesn't clear it, this method is usable as follows.
|
106
|
+
*
|
107
|
+
* END { STDOUT.nonblock = false }
|
108
|
+
* STDOUT.write_nonblock("foo")
|
109
|
+
*
|
110
|
+
* Since the flag is shared across processes and
|
111
|
+
* many non-Ruby commands doesn't expect standard I/O with non-blocking mode,
|
112
|
+
* it would be safe to clear the flag before Ruby program exits.
|
113
|
+
*
|
114
|
+
* For example following Ruby program leaves STDIN/STDOUT/STDER non-blocking mode.
|
115
|
+
* (STDIN, STDOUT and STDERR are connected to a terminal.
|
116
|
+
* So making one of them nonblocking-mode effects other two.)
|
117
|
+
* Thus cat command try to read from standard input and
|
118
|
+
* it causes "Resource temporarily unavailable" error (EAGAIN).
|
119
|
+
*
|
120
|
+
* % ruby -e '
|
121
|
+
* STDOUT.write_nonblock("foo\n")'; cat
|
122
|
+
* foo
|
123
|
+
* cat: -: Resource temporarily unavailable
|
124
|
+
*
|
125
|
+
* Clearing the flag makes the behavior of cat command normal.
|
126
|
+
* (cat command waits input from standard input.)
|
127
|
+
*
|
128
|
+
* % ruby -rio/nonblock -e '
|
129
|
+
* END { STDOUT.nonblock = false }
|
130
|
+
* STDOUT.write_nonblock("foo")
|
131
|
+
* '; cat
|
132
|
+
* foo
|
133
|
+
*
|
77
134
|
*/
|
78
135
|
static VALUE
|
79
|
-
rb_io_nonblock_set(VALUE
|
136
|
+
rb_io_nonblock_set(VALUE self, VALUE value)
|
80
137
|
{
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
138
|
+
if (RTEST(value)) {
|
139
|
+
rb_io_t *fptr;
|
140
|
+
GetOpenFile(self, fptr);
|
141
|
+
rb_io_set_nonblock(fptr);
|
142
|
+
}
|
143
|
+
else {
|
144
|
+
int descriptor = rb_io_descriptor(self);
|
145
|
+
io_nonblock_set(descriptor, get_fcntl_flags(descriptor), RTEST(value));
|
146
|
+
}
|
147
|
+
|
148
|
+
return self;
|
88
149
|
}
|
89
150
|
|
151
|
+
#endif /* RUBY_IO_NONBLOCK_METHODS */
|
152
|
+
|
90
153
|
static VALUE
|
91
154
|
io_nonblock_restore(VALUE arg)
|
92
155
|
{
|
93
156
|
int *restore = (int *)arg;
|
94
|
-
|
95
|
-
rb_sys_fail(0);
|
157
|
+
set_fcntl_flags(restore[0], restore[1]);
|
96
158
|
return Qnil;
|
97
159
|
}
|
98
160
|
|
99
161
|
/*
|
100
162
|
* call-seq:
|
101
|
-
* io.nonblock {|io| } ->
|
102
|
-
* io.nonblock(boolean) {|io| } ->
|
163
|
+
* io.nonblock {|io| } -> object
|
164
|
+
* io.nonblock(boolean) {|io| } -> object
|
103
165
|
*
|
104
166
|
* Yields +self+ in non-blocking mode.
|
105
167
|
*
|
@@ -107,24 +169,25 @@ io_nonblock_restore(VALUE arg)
|
|
107
169
|
* The original mode is restored after the block is executed.
|
108
170
|
*/
|
109
171
|
static VALUE
|
110
|
-
rb_io_nonblock_block(int argc, VALUE *argv, VALUE
|
172
|
+
rb_io_nonblock_block(int argc, VALUE *argv, VALUE self)
|
111
173
|
{
|
112
174
|
int nb = 1;
|
113
|
-
rb_io_t *fptr;
|
114
|
-
int f, restore[2];
|
115
175
|
|
116
|
-
|
176
|
+
int descriptor = rb_io_descriptor(self);
|
177
|
+
|
117
178
|
if (argc > 0) {
|
118
|
-
|
119
|
-
|
120
|
-
|
179
|
+
VALUE v;
|
180
|
+
rb_scan_args(argc, argv, "01", &v);
|
181
|
+
nb = RTEST(v);
|
121
182
|
}
|
122
|
-
|
123
|
-
|
124
|
-
restore[
|
125
|
-
|
126
|
-
|
127
|
-
|
183
|
+
|
184
|
+
int current_flags = get_fcntl_flags(descriptor);
|
185
|
+
int restore[2] = {descriptor, current_flags};
|
186
|
+
|
187
|
+
if (!io_nonblock_set(descriptor, current_flags, nb))
|
188
|
+
return rb_yield(self);
|
189
|
+
|
190
|
+
return rb_ensure(rb_yield, self, io_nonblock_restore, (VALUE)restore);
|
128
191
|
}
|
129
192
|
#else
|
130
193
|
#define rb_io_nonblock_set rb_f_notimplement
|
@@ -134,7 +197,10 @@ rb_io_nonblock_block(int argc, VALUE *argv, VALUE io)
|
|
134
197
|
void
|
135
198
|
Init_nonblock(void)
|
136
199
|
{
|
200
|
+
#ifndef RUBY_IO_NONBLOCK_METHODS
|
137
201
|
rb_define_method(rb_cIO, "nonblock?", rb_io_nonblock_p, 0);
|
138
202
|
rb_define_method(rb_cIO, "nonblock=", rb_io_nonblock_set, 1);
|
203
|
+
#endif
|
204
|
+
|
139
205
|
rb_define_method(rb_cIO, "nonblock", rb_io_nonblock_block, -1);
|
140
206
|
}
|
metadata
CHANGED
@@ -1,34 +1,28 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-nonblock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nobu Nakada
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-12-13 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Enables non-blocking mode with IO class
|
14
14
|
email:
|
15
15
|
- nobu@ruby-lang.org
|
16
16
|
executables: []
|
17
|
-
extensions:
|
17
|
+
extensions:
|
18
|
+
- ext/io/nonblock/extconf.rb
|
18
19
|
extra_rdoc_files: []
|
19
20
|
files:
|
20
|
-
- ".gitignore"
|
21
|
-
- ".travis.yml"
|
22
21
|
- COPYING
|
23
|
-
- Gemfile
|
24
22
|
- README.md
|
25
|
-
- Rakefile
|
26
|
-
- bin/console
|
27
|
-
- bin/setup
|
28
23
|
- ext/io/nonblock/depend
|
29
24
|
- ext/io/nonblock/extconf.rb
|
30
25
|
- ext/io/nonblock/nonblock.c
|
31
|
-
- io-nonblock.gemspec
|
32
26
|
homepage: https://github.com/ruby/io-nonblock
|
33
27
|
licenses:
|
34
28
|
- Ruby
|
@@ -51,7 +45,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
51
45
|
- !ruby/object:Gem::Version
|
52
46
|
version: '0'
|
53
47
|
requirements: []
|
54
|
-
rubygems_version: 3.
|
48
|
+
rubygems_version: 3.5.0.dev
|
55
49
|
signing_key:
|
56
50
|
specification_version: 4
|
57
51
|
summary: Enables non-blocking mode with IO class
|
data/.gitignore
DELETED
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
require "rake/testtask"
|
3
|
-
|
4
|
-
Rake::TestTask.new(:test) do |t|
|
5
|
-
t.libs << "test"
|
6
|
-
t.libs << "lib"
|
7
|
-
t.test_files = FileList["test/**/test_*.rb"]
|
8
|
-
end
|
9
|
-
|
10
|
-
require 'rake/extensiontask'
|
11
|
-
Rake::ExtensionTask.new("io/nonblock")
|
12
|
-
task :default => :test
|
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "io/nonblock"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
data/bin/setup
DELETED
data/io-nonblock.gemspec
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Gem::Specification.new do |spec|
|
2
|
-
spec.name = "io-nonblock"
|
3
|
-
spec.version = "0.1.0"
|
4
|
-
spec.authors = ["Nobu Nakada"]
|
5
|
-
spec.email = ["nobu@ruby-lang.org"]
|
6
|
-
|
7
|
-
spec.summary = %q{Enables non-blocking mode with IO class}
|
8
|
-
spec.description = %q{Enables non-blocking mode with IO class}
|
9
|
-
spec.homepage = "https://github.com/ruby/io-nonblock"
|
10
|
-
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
11
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
12
|
-
|
13
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
14
|
-
spec.metadata["source_code_uri"] = spec.homepage
|
15
|
-
|
16
|
-
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
17
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
-
end
|
19
|
-
spec.bindir = "exe"
|
20
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
-
spec.require_paths = ["lib"]
|
22
|
-
end
|