io-nonblock 0.1.0 → 0.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.
- 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
|