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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7f197b776a167ab8e464d769208e51374e123069c567469f5ace8329bcdaa37
4
- data.tar.gz: 482709a0e5dd558e54a6bcd1329df17a91d36cb6910585446b1685a5389d5af1
3
+ metadata.gz: 72722b1ffc6a232b51665e937ecabe164a15e2dbccdb35628fe158db78e56713
4
+ data.tar.gz: 491aa2cbbb825667d190e5dca3f3ef44abb7fcc65d2a5080e33f5fa4936142f0
5
5
  SHA512:
6
- metadata.gz: 5e55dadc9959a30f527985b7afdb0297dfbdc9b0680a49037099ce0205301992cfbcccd84aa52f18704529d31afb30bc1b033f2284902714fea5e38e5344f60f
7
- data.tar.gz: '00328f04184febef11667804acc88257c28383fbfb65a54649b16fbe1937172af000798ca201aaf2cdd44c572b37dff48b0cc14cdc436b162efc8e437b3e89cd'
6
+ metadata.gz: 9c1e8c2abd77710e460dc12c39a89f2bf3e2466208bc422e97ec1891629d71d569c95c8b80beadd0ef5f5673c53f4101f016930038770266b2f62732972f7b65
7
+ data.tar.gz: 3045f739c5bdcbef2c1335bfd0024842e5be44d0af0a3a90fb49c3ca9151fa02e74520cc854b3207e328b8c1a7f19fde5b580ad121c511590860e484de5b335d
@@ -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))
@@ -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
- io_nonblock_mode(int fd)
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 io_nonblock_mode(fd) ((void)(fd), 0)
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
- rb_io_t *fptr;
43
- GetOpenFile(io, fptr);
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
- if (fcntl(fd, F_SETFL, f) == -1)
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 io, VALUE nb)
136
+ rb_io_nonblock_set(VALUE self, VALUE value)
80
137
  {
81
- rb_io_t *fptr;
82
- GetOpenFile(io, fptr);
83
- if (RTEST(nb))
84
- rb_io_set_nonblock(fptr);
85
- else
86
- io_nonblock_set(fptr->fd, io_nonblock_mode(fptr->fd), RTEST(nb));
87
- return io;
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
- if (fcntl(restore[0], F_SETFL, restore[1]) == -1)
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| } -> io
102
- * io.nonblock(boolean) {|io| } -> 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 io)
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
- GetOpenFile(io, fptr);
176
+ int descriptor = rb_io_descriptor(self);
177
+
117
178
  if (argc > 0) {
118
- VALUE v;
119
- rb_scan_args(argc, argv, "01", &v);
120
- nb = RTEST(v);
179
+ VALUE v;
180
+ rb_scan_args(argc, argv, "01", &v);
181
+ nb = RTEST(v);
121
182
  }
122
- f = io_nonblock_mode(fptr->fd);
123
- restore[0] = fptr->fd;
124
- restore[1] = f;
125
- if (!io_nonblock_set(fptr->fd, f, nb))
126
- return rb_yield(io);
127
- return rb_ensure(rb_yield, io, io_nonblock_restore, (VALUE)restore);
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.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nobu Nakada
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-18 00:00:00.000000000 Z
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.2.0.rc.1
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
@@ -1,11 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- *.bundle
10
- *.dll
11
- *.so
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.8.0
6
- before_install: gem install bundler -v 2.1.4
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in etc.gemspec
4
- gemspec
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
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
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